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
解题方法: 给个别人的链接
初学CDQ花了快1天理解这个原理,再推荐一位大牛写的关于CDQ分治的总结: 见这里 初级CDQ大概理解了,不过CDQ套CDQ,以及高维偏序还不理解,强撸题吧!注意这个题数组开小不是RE,是WA,神坑。
//bzoj 1176
//1维排序,二维分治,3维BIT
#include <bits/stdc++.h>
using namespace std;
const int maxq = 200010;
const int maxn = 500010;
int S, W, ans[maxq];
inline int read()
{
char ch=getchar();
int f=1,x=0;
while(!(ch>='0'&&ch<='9')){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+(ch-'0');ch=getchar();}
return x*f;
}
namespace BIT{
int tree[2000010];
inline int lowbit(int x) {return x & -x;}
inline void update(int x, int y) {for(int i = x; i <= W; i+=lowbit(i)) tree[i] += y;}
inline int query(int x) {int res = 0; for(int i = x; i; i -= lowbit(i)) res += tree[i]; return res;}
}
using namespace BIT;
struct Q{
int id, x, y, opt, del, ID;
Q(){}
Q(int id, int x, int y, int opt, int del, int ID) : id(id), x(x), y(y), opt(opt), del(del), ID(ID) {}
bool operator < (const Q &rhs) const{
return (x == rhs.x && y == rhs.y) ? opt < rhs.opt : ((x == rhs.x) ? y < rhs.y : x < rhs.x);
}
}q[maxq*4], tmp[maxq*4];
void CDQ(int l, int r){
if(l == r) return ;
int mid = (l+r)>>1, z1 = l, z2 = mid + 1;
for(int i = l; i <= r; i++){
if(q[i].opt == 1 && q[i].id <= mid) update(q[i].y, q[i].del);
if(q[i].opt == 2 && q[i].id > mid) ans[q[i].ID] += query(q[i].y) * q[i].del;
}
for(int i = l; i <= r; i++) if(q[i].opt == 1 && q[i].id <= mid) update(q[i].y, -q[i].del);
for(int i = l; i <= r; i++) if(q[i].id <= mid) tmp[z1++] = q[i]; else tmp[z2++] = q[i];
for(int i = l; i <= r; i++) q[i] = tmp[i];
CDQ(l, mid);
CDQ(mid + 1, r);
}
int t, z;
void presolve(int x1, int y1, int x2, int y2){ //操作拆分 sum(x2,y2)+sum(x1-1,y1-1)+sum(x1-1,y2)-sum(x2,y1-1)
z++;
t++; q[t].id = t; q[t].ID = z; q[t].x = x1 - 1; q[t].y = y1 - 1; q[t].del = 1; q[t].opt = 2;
t++; q[t].id = t; q[t].ID = z; q[t].x = x2; q[t].y = y2; q[t].del = 1; q[t].opt = 2;
t++; q[t].id = t; q[t].ID = z; q[t].x = x1 - 1; q[t].y = y2; q[t].del = -1; q[t].opt = 2;
t++; q[t].id = t; q[t].ID = z; q[t].x = x2; q[t].y = y1 - 1; q[t].del = -1; q[t].opt = 2;
}
int main(){
//scanf("%d%d", &S, &W);
S = read(); W = read();
t = z = 0;
while(1){
int cmd;
//scanf("%d", &cmd);
cmd = read();
if(cmd == 3) break;
if(cmd == 1){t++; //scanf("%d%d%d", &q[t].x, &q[t].y, &q[t].del);
q[t].x = read(), q[t].y = read(), q[t].del = read();
q[t].id = t; q[t].opt = 1; }
if(cmd == 2){
int x1, x2, y1, y2;
//scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
x1 = read(), y1 = read(), x2 = read(), y2 = read();
presolve(x1, y1, x2, y2);
}
}
sort(q + 1, q + t + 1);
CDQ(1, t);
for(int i = 1; i <= z; i++) printf("%d\n", ans[i]);
return 0;
}