码迷,mamicode.com
首页 > 编程语言 > 详细

bzoj 1176 [Balkan2007]Mokia - CDQ分治 - 树状数组

时间:2017-07-29 12:45:04      阅读:146      评论:0      收藏:0      [点我收藏+]

标签:accept   print   ==   ini   计算   led   can   超过   win   

Description

维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000.

Input

第一行两个整数,S,W;其中S为矩阵初始值;W为矩阵大小

接下来每行为一下三种输入之一(不包含引号):

"1 x y a"

"2 x1 y1 x2 y2"

"3"

输入1:你需要把(x,y)(第x行第y列)的格子权值增加a

输入2:你需要求出以左下角为(x1,y1),右上角为(x2,y2)的矩阵内所有格子的权值和,并输出

输入3:表示输入结束

Output

对于每个输入2,输出一行,即输入2的答案

Sample Input

0 4
1 2 3 3
2 1 1 3 3
1 2 2 2
2 2 2 3 4
3

Sample Output

3
5

HINT

 

保证答案不会超过int范围


  题目大意 (数据结构题题面太简洁不需要大意)

  显然树套树加动态开点可以过掉这道题,然而表示并不想写。

  由于支持离线可以考虑CDQ分治。

  首先对于一个左上角在(1, 1),右下角在(x, y)的矩阵的权值和,是可以求出来的。首先以x为第一关键字,y为第二关键字,opt为第三关键字排序,然后用树状数组维护y = i上的和。

  所以我们将一个询问拆成4个询问,再根据简单容斥计算出。

Code

  1 /**
  2  * bzoj
  3  * Problem#1176
  4  * Accepted
  5  * Time:6964ms
  6  * Memory:33940k
  7  */
  8 #include <bits/stdc++.h>
  9 using namespace std;
 10 typedef bool boolean;
 11 #ifndef WIN32
 12 #define Auto "%lld"
 13 #else
 14 #define Auto "%I64d"
 15 #endif
 16 
 17 #define lowbit(x) (x) & (-x)
 18 #define LL long long
 19 
 20 typedef class IndexedTree {
 21     public:
 22         int s;
 23         LL *lis;
 24         
 25         IndexedTree() {        }
 26         IndexedTree(int s):s(s) {
 27             lis = new LL[(s + 1)];
 28             memset(lis, 0, sizeof(LL) * (s + 1));
 29         }
 30         
 31         inline void add(int idx, int x) {
 32             for(; idx <= s; idx += lowbit(idx))
 33                 lis[idx] += x;
 34         }
 35         
 36         inline LL getSum(int idx) {
 37             LL ret = 0;
 38             for(; idx; idx -= lowbit(idx))
 39                 ret += lis[idx];
 40             return ret;
 41         }
 42 }IndexedTree;
 43 
 44 typedef class Query {
 45     public:
 46         int x;
 47         int y;
 48         int opt;
 49         int sign;
 50         int id;
 51         
 52         Query(int x = 0, int y = 0, int opt = 0, int sign = 0, int id = 0):x(x), y(y), opt(opt), sign(sign), id(id) {        }
 53         
 54         boolean operator < (Query b) const {
 55             if(x != b.x)    return x < b.x;
 56             if(y != b.y)    return y < b.y;
 57             return opt < b.opt;
 58         }
 59 }Query;
 60 
 61 int s, w;
 62 int cnt = 0;
 63 IndexedTree it;
 64 vector<Query> qs;
 65 vector<Query> bq;
 66 LL *res;
 67 
 68 inline void init() {
 69     int opt, x0, y0, x1, y1, c;
 70     scanf("%d%d", &s, &w);
 71     while(~scanf("%d", &opt) && opt != 3) {
 72         scanf("%d%d", &x0, &y0);
 73         if(opt == 1) {
 74             scanf("%d", &c);
 75             qs.push_back(Query(x0, y0, opt, c, cnt));
 76         } else {
 77             scanf("%d%d", &x1, &y1);
 78             qs.push_back(Query(x1, y1, opt, 1, cnt));
 79             qs.push_back(Query(x0 - 1, y1, opt, -1, cnt));
 80             qs.push_back(Query(x1, y0 - 1, opt, -1, cnt));
 81             qs.push_back(Query(x0 - 1, y0 - 1, opt, 1, cnt));
 82             bq.push_back(Query(x0, y0, x1, y1, cnt));
 83         }
 84         cnt++;
 85     }
 86 }
 87 
 88 void CDQDividing(int l, int r, vector<Query> &que) {
 89     if(que.empty())    return;
 90     if(l == r)    return;
 91     
 92     int mid = (l + r) >> 1;
 93     for(int i = 0; i < (signed)que.size(); i++) {
 94         if(que[i].opt == 1 && que[i].id <= mid)
 95             it.add(que[i].y, que[i].sign);
 96         if(que[i].opt == 2 && que[i].id > mid)
 97             res[que[i].id] += it.getSum(que[i].y) * que[i].sign;
 98     }
 99     
100     for(int i = 0; i < (signed)que.size(); i++)
101         if(que[i].opt == 1 && que[i].id <= mid)
102             it.add(que[i].y, -que[i].sign);
103     
104     vector<Query> ql, qr;
105     for(int i = 0; i < (signed)que.size(); i++)
106         if(que[i].id <= mid)
107             ql.push_back(que[i]);
108         else
109             qr.push_back(que[i]);
110     
111     que.clear();
112     CDQDividing(l, mid, ql);
113     CDQDividing(mid + 1, r, qr);
114 }
115 
116 inline void solve() {
117     res = new LL[(cnt + 1)];
118     memset(res, 0, sizeof(LL) * (cnt + 1));
119     sort(qs.begin(), qs.end());
120     it = IndexedTree(w);
121     CDQDividing(0, cnt - 1, qs);
122     
123     for(int i = 0; i < (signed)bq.size(); i++)
124         printf(Auto"\n", res[bq[i].id] + (bq[i].opt - bq[i].x + 1) * (bq[i].sign - bq[i].y + 1) * s);
125 }
126 
127 int main() {
128     init();
129     solve();
130     return 0;
131 }

Description

维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000.

Input

第一行两个整数,S,W;其中S为矩阵初始值;W为矩阵大小

接下来每行为一下三种输入之一(不包含引号):

"1 x y a"

"2 x1 y1 x2 y2"

"3"

输入1:你需要把(x,y)(第x行第y列)的格子权值增加a

输入2:你需要求出以左下角为(x1,y1),右上角为(x2,y2)的矩阵内所有格子的权值和,并输出

输入3:表示输入结束

Output

对于每个输入2,输出一行,即输入2的答案

Sample Input

0 4
1 2 3 3
2 1 1 3 3
1 2 2 2
2 2 2 3 4
3

Sample Output

3
5

HINT

 

保证答案不会超过int范围

bzoj 1176 [Balkan2007]Mokia - CDQ分治 - 树状数组

标签:accept   print   ==   ini   计算   led   can   超过   win   

原文地址:http://www.cnblogs.com/yyf0309/p/7255358.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!