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
1 2 3 3
2 1 1 3 3
1 2 2 2
2 2 2 3 4
3
Sample Output
3
5
5
HINT
保证答案不会超过int范围
题解:
二维树状数组显然没法处理.
考虑cdq分治,对于(l,r),处理(l,mid)中的修改操作对(mid+1,r)中的询问的影响.
分析一下就是有若干点和若干矩形,然后需要计算每个矩形包含多少个点,
这是个经典问题,按x排序,对y建树状数组即可.
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 2000010
#define M 200000
using namespace std;
int n,s,ans[M],num,tot,x1,y1,kind,x2,y2,t[N];
struct use{int x,y,v,kind,id,p;}q[M<<2],tr[M<<2];
int read(){
int x(0);char ch=getchar();
while (ch<'0'||ch>'9') ch=getchar();
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x;
}
void get(){
x1=read();y1=read();x2=read();y2=read();num++;
q[++tot].p=num;q[tot].id=tot;q[tot].kind=1;q[tot].x=x1-1;q[tot].y=y1-1;q[tot].v=1;
q[++tot].p=num;q[tot].id=tot;q[tot].kind=1;q[tot].x=x2;q[tot].y=y2;q[tot].v=1;
q[++tot].p=num;q[tot].id=tot;q[tot].kind=1;q[tot].x=x1-1;q[tot].y=y2;q[tot].v=-1;
q[++tot].p=num;q[tot].id=tot;q[tot].kind=1;q[tot].x=x2;q[tot].y=y1-1;q[tot].v=-1;
}
bool cmp(use a,use b){
if (a.x==b.x){
if (a.y==b.y) return a.id<b.id;
else return a.y<b.y;
}
else return a.x<b.x;
}
int lowbit(int x){
return x&(-x);
}
void add(int x,int v){
for (int i=x;i<=n;i+=lowbit(i)) t[i]+=v;
}
int query(int x){
int ans(0);
for (int i=x;i;i-=lowbit(i)) ans+=t[i];
return ans;
}
void solve(int l,int r){
if (l==r) return;
int mid=(l+r)>>1,l1=l,l2=mid+1;
for (int i=l;i<=r;i++){
if (q[i].id<=mid&&!q[i].kind) add(q[i].y,q[i].v);
if (q[i].id>mid&&q[i].kind==1) ans[q[i].p]+=q[i].v*query(q[i].y);
}
for (int i=l;i<=r;i++)
if (q[i].id<=mid&&!q[i].kind) add(q[i].y,-q[i].v);
for (int i=l;i<=r;i++)
if (q[i].id<=mid) tr[l1++]=q[i];
else tr[l2++]=q[i];
for (int i=l;i<=r;i++) q[i]=tr[i];
solve(l,mid);solve(mid+1,r);
}
int main(){
s=read();n=read();
while (1){
kind=read();
if (kind==3) break;
if (kind==1){
q[++tot].x=read();q[tot].y=read();
q[tot].v=read();q[tot].id=tot;
}
else get();
}
sort(q+1,q+tot+1,cmp);
solve(1,tot);
for (int i=1;i<=num;i++) printf("%d\n",ans[i]);
}