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的答案
题解:
我们可以按照操作的时间,坐标x,坐标y形成三维偏序就好做了
由于操作的时间本身就是有序的,所以不需要排序就可以直接CDQ分治处理坐标x,在坐标x有序的情况下将有贡献的y值放入树状数组记录即可
然后查询做一个简单的容斥拆成4的点询问即可
AC代码:
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#include<ext/rope>
using namespace std;
using namespace __gnu_cxx;
#define pii pair<int,int>
#define mp(a,b) make_pair(a,b)
const int MAXN = 2e5+10;
const int MOD = 100003;
const int INF = 0x3f3f3f3f;
struct node{ int x,y,val,id; }a[MAXN],b[MAXN];
int s,w,tot,cnt,ans[MAXN],q[MAXN];
namespace BIT{
int bit[MAXN*10];
inline int lowbit(int x){ return x&-x; }
inline void add(int x,int val){ for(int i=x;i<=w;i+=lowbit(i)) bit[i]+=val; }
inline int query(int x,int res=0){ for(int i=x;i;i-=lowbit(i)) res+=bit[i]; return res; }
}
using namespace BIT;
void CDQ(int l,int r){
if(l>=r) return; int mid=(l+r)>>1;
CDQ(l,mid); CDQ(mid+1,r);
int p=l,q=mid+1,x=l;
while(q<=r){
while(a[p].x<=a[q].x && p<=mid){
if(a[p].id==0) add(a[p].y,a[p].val);
b[x++]=a[p++];
}
if(a[q].id) ans[a[q].val]+=query(a[q].y);
b[x++]=a[q++];
}
for(int i=l;i<p;i++) if(a[i].id==0) add(a[i].y,-a[i].val);
while(p<=mid) b[x++]=a[p++];
while(q<=r) b[x++]=a[q++];
for(int i=l;i<=r;i++) a[i]=b[i];
}
signed main(){
#ifndef ONLINE_JUDGE
freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin);
#endif // ONLINE_JUDGE
scanf("%d%d",&s,&w);
while(true){
int op; scanf("%d",&op);
if(op==3) break;
if(op==1){
int x,y,val; scanf("%d%d%d",&x,&y,&val);
a[++cnt] = node{x,y,val,0};
}else if(op==2){
int x,y,xx,yy; scanf("%d%d%d%d",&x,&y,&xx,&yy);
q[++tot]=cnt+1;
ans[cnt+4] += (yy-y+1)*(xx-x+1)*s;
a[++cnt]=node{x-1,y-1,cnt,1};
a[++cnt]=node{x-1,yy,cnt,1};
a[++cnt]=node{xx,y-1,cnt,1};
a[++cnt]=node{xx,yy,cnt,1};
}
}
CDQ(1,cnt);
for(int i=1;i<=tot;i++)
printf("%d\n",ans[q[i]+3]-ans[q[i]+2]-ans[q[i]+1]+ans[q[i]]);
return 0;
}