bzoj2683(要改一点代码)&&bzoj1176: [Balkan2007]Mokia
仍然是一道cdq模版。。
那么对于一个询问,容斥一下分成四个,变成问(1,1)~(x,y),那么对于x,y,修改只有x'<=x&&y'<=y,才对询问有影响,那么加上读入顺序,就是一个三维偏序了。
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; struct node { int tp,x,y,v,be;//第一维时间已经有序 //tp=0 表示修改 v为修改的值 //tp=-1、1询问 v为所求值 }a[210000];int len; void ins(int tp,int x,int y,int v,int be) { len++; a[len].tp=tp; a[len].x=x;a[len].y=y; a[len].v=v;a[len].be=be; } //---------------------------------- int n,s[2100000]; int lowbit(int x){return x&-x;} void add(int x,int k) { while(x<=n) { s[x]+=k; x+=lowbit(x); } } int getsum(int x) { int ans=0; while(x>=1) { ans+=s[x]; x-=lowbit(x); } return ans; } //---------------树状数组----------------- node t[210000]; void cdq(int l,int r) { if(l==r)return ; int mid=(l+r)/2; cdq(l,mid); cdq(mid+1,r); int i=l,j=mid+1,p=l; while(i<=mid&&j<=r) { if(a[i].x<=a[j].x) { if(a[i].tp==0)add(a[i].y,a[i].v); t[p++]=a[i++]; } else { if(a[j].tp!=0)a[j].v+=getsum(a[j].y); t[p++]=a[j++]; } } while(i<=mid) { if(a[i].tp==0)add(a[i].y,a[i].v); t[p++]=a[i++]; } while(j<=r) { if(a[j].tp!=0)a[j].v+=getsum(a[j].y); t[p++]=a[j++]; } for(int i=l;i<=mid;i++) if(a[i].tp==0)add(a[i].y,-a[i].v); for(int i=l;i<=r;i++)a[i]=t[i]; } //-------------------cdq------------------------ int ans[11000],ansl; int main() { int S; scanf("%d%d",&S,&n); int op,x1,y1,x2,y2,v;len=0; while(scanf("%d",&op)!=EOF) { if(op==3)break; if(op==1) { scanf("%d%d%d",&x1,&y1,&v); ins(0,x1,y1,v,0); } else { ansl++; scanf("%d%d%d%d",&x1,&y1,&x2,&y2); if(x1-1>0&&y1-1>0)ins(1,x1-1,y1-1,0,ansl); if(x1-1>0)ins(-1,x1-1,y2,0,ansl); if(y1-1>0)ins(-1,x2,y1-1,0,ansl); ins(1,x2,y2,0,ansl); } } cdq(1,len); memset(ans,0,sizeof(ans)); for(int i=1;i<=len;i++) if(a[i].tp!=0)ans[a[i].be]+=a[i].v*a[i].tp; for(int i=1;i<=ansl;i++)printf("%d\n",ans[i]); return 0; }
pain and happy in the cruel world.