維護一個W*W的矩陣,初始值均爲S.每次操做能夠增長某格子的權值,或詢問某子矩陣的總權值.node
修改操做數M<=160000,詢問數Q<=10000,W<=2000000.ios
BZOJ1176: [Balkan2007]Mokiaphp
維護一個W*W的矩陣,初始值均爲S.每次操做能夠增長某格子的權值,或詢問某子矩陣的總權值.node
修改操做數M<=160000,詢問數Q<=10000,W<=2000000.ios
第一行兩個整數,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:表示輸入結束數組
對於每一個輸入2,輸出一行,即輸入2的答案spa
保證答案不會超過int範圍blog
題解Here!ip
矩陣上單點修改,區間查詢,二維線段樹就能夠了。get
可是w<=2,000,000。it
並且我又不會cdq分治/K-D Tree。io
因此只能樹狀數組套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; }