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范围
题解Here!
矩阵上单点修改,区间查询,二维线段树就可以了。
但是w<=2,000,000。
而且我又不会cdq分治/K-D Tree。
所以只能树状数组套Treap。
将询问拆分一下即可。
附代码:
#include<iostream> #include<algorithm> #include<cstdio> #define MAXN 2000010 using namespace std; int n; struct node{ node* son[2]; int v,w,x,sum; node(){ son[0]=son[1]=NULL; w=rand(); v=sum=x=0; } }; node* root[MAXN]; inline int read(){ int date=0,w=1;char c=0; while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();} while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();} return date*w; } inline void maintain(node* &u){ if(u==NULL)return; u->sum=u->v; if(u->son[0]!=NULL)u->sum+=u->son[0]->sum; if(u->son[1]!=NULL)u->sum+=u->son[1]->sum; } inline void turn(node* &u,int f){ node* t=u->son[f^1]; u->son[f^1]=t->son[f]; t->son[f]=u; maintain(u); maintain(t); u=t; } void insert(node* &u,int x,int v){ if(u==NULL){ u=new node; u->x=x; u->v=u->sum=v; return; } else if(u->x==x){ u->v+=v;u->sum+=v; return; } int y=u->x<x?1:0; insert(u->son[y],x,v); if(u->son[y]->w>u->w)turn(u,y^1); maintain(u); } int query(node* u,int x){ int s=0; while(u!=NULL){ if(u->x>x)u=u->son[0]; else{ if(u->son[0]!=NULL)s+=u->son[0]->sum; s+=u->v; u=u->son[1]; } } return s; } inline int lowbit(int x){return x&(-x);} inline void update(int x,int y,int v){ for(int i=x;i<=n;i+=lowbit(i))insert(root[i],y,v); } inline int sum(int x,int y){ int s=0; for(int i=x;i;i-=lowbit(i))s+=query(root[i],y); return s; } void work(){ while(1){ int f=read(); if(f==3)break; if(f==1){ int x=read(),y=read(),k=read(); update(x,y,k); } else if(f==2){ int x1=read(),y1=read(),x2=read(),y2=read(); printf("%d ",sum(x2,y2)-sum(x1-1,y2)-sum(x2,y1-1)+sum(x1-1,y1-1)); } } } void init(){ srand(987); int x=read(); n=read(); } int main(){ init(); work(); return 0; }