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\n",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;
}