bzoj2683 简单题 (cdq分治 + 树状数组)
2017-11-26 12:11
399 查看
bzoj2683 简单题
原题地址:http://www.lydsy.com/JudgeOnline/problem.php?id=2683题意:
你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作:
命令 | 参数限制 | 内容 |
---|---|---|
1 x y A | 1<=x,y<=N,A是正整数 | 将格子x,y里的数字加上A |
2 x1 y1 x2 y2 | 1<=x1<= x2<=N,1<=y1<= y2<=N | 输出x1 y1 x2 y2这个矩形内的数字和 |
3 | 无 | 终止程序 |
1<=N<=500000,操作数不超过200000个,内存限制20M。
题解:
内存20M,又因为N很大,上数据结构比较困难。
于是想到cdq分治。
对于一个查询(x1,y1,x2,y2)
我们把它分成四个查询 +(x1-1,y1-1),-(x1-1,y2), -(x2,y1-1) ,+(x2,y2),前缀和的加加减减。
这样只需考虑哪些操作会对我的查询有影响。
三个参数(x,y,time)
显然是三维都<=当前查询就会有影响,
这样就成了一个三维偏序问题,只不过树状数组里面存的,是带来的影响(加的数值)
于是cdq分治时用作半边的所有操作,去计算对右边所有询问的影响即可。
树状数组用了的才清。
代码:
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> using namespace std; const int N=500005; const int M=1000005; struct node { int typ,x,y,w,id; //类型,xy坐标,时刻, 影响(权值 或 +/-),ID friend bool operator<(const node &A,const node &B) {return (A.x!=B.x)? A.x<B.x:A.y<=B.y;} }Q[M],R[M]; int n,tim=0,tail=0,qs=0,ans ; struct B_I_T { int c ; void add(int x,int val) { for(int i=x;i<=n;i=i+(i&(-i))) c[i]+=val; } int query(int x) { int ret=0; for(int i=x;i>0;i=i-(i&(-i))) ret+=c[i]; return ret; } void clear(int x) { for(int i=x;i<=n;i=i+(i&(-i))) c[i]=0; } }Bit; void cdq(int lf,int rg) { if(rg-lf<=0) return; int mid=(lf+rg)>>1; cdq(lf,mid); cdq(mid+1,rg); int p1=lf; int p2=mid+1; int tail=lf-1; while(p1<=mid&&p2<=rg) { if(Q[p1]<Q[p2]) { if(Q[p1].typ==0) Bit.add(Q[p1].y,Q[p1].w); R[++tail]=Q[p1++]; } else { if(Q[p2].typ==1) ans[Q[p2].id]+=Q[p2].w*Bit.query(Q[p2].y); R[++tail]=Q[p2++]; } } while(p1<=mid) R[++tail]=Q[p1++]; while(p2<=rg) { if(Q[p2].typ==1) ans[Q[p2].id]+=Q[p2].w*Bit.query(Q[p2].y); R[++tail]=Q[p2++]; } for(int i=lf;i<=rg;i++) { Bit.clear(R[i].y); Q[i]=R[i]; } } int main() { scanf("%d",&n); n++; while(1) { int opt; scanf("%d",&opt); if(opt==1)//1 x y A ,将格子x,y里的数字加上A { ++tail; scanf("%d%d%d",&Q[tail].x,&Q[tail].y,&Q[tail].w); Q[tail].x++; Q[tail].y++; Q[tail].typ=0; } else if(opt==2)//2 x1 y1 x2 y2,输出x1 y1 x2 y2这个矩形内的数字和 { int x1,y1,x2,y2; scanf("%d%d%d%d",&x1,&y1,&x2,&y2); x1++; x2++; y1++; y2++; qs++; Q[++tail].typ=1; Q[tail].x=x1-1; Q[tail].y=y1-1; Q[tail].w=1; Q[tail].id=qs; Q[++tail].typ=1; Q[tail].x=x1-1; Q[tail].y=y2; Q[tail].w=-1; Q[tail].id=qs; Q[++tail].typ=1; Q[tail].x=x2; Q[tail].y=y1-1; Q[tail].w=-1; Q[tail].id=qs; Q[++tail].typ=1; Q[tail].x=x2; Q[tail].y=y2; Q[tail].w=1; Q[tail].id=qs; } if(opt==3) break; } cdq(1,tail); for(int i=1;i<=qs;i++) printf("%d\n",ans[i]); return 0; }
相关文章推荐
- BZOJ 2683: 简单题【CDQ分治 + 树状数组
- 【BZOJ2683】简单题【CDQ分治】
- BZOJ2683 简单题(CDQ分治)
- BZOJ2683 简单题(CDQ分治)
- BZOJ 2683: 简单题(CDQ分治)
- bzoj 1176: [Balkan2007]Mokia&&2683: 简单题 -- cdq分治
- Bzoj2683 简单题 [CDQ分治]
- Bzoj 2683: 简单题(CDQ分治)
- BZOJ 2683: 简单题 [CDQ分治]
- [BZOJ2683]简单题(cdq分治)
- BZOJ 2683 简单题 ——CDQ分治
- [BZOJ2683]简单题(cdq分治)
- BZOJ 1176: [Balkan2007]Mokia&&2683: 简单题|cdq分治
- 【CDQ分治】BZOJ2683 简单题
- BZOJ 4553 [Tjoi2016&Heoi2016]序列 ——CDQ分治 树状数组
- 【BZOJ2683】简单题 [分治][树状数组]
- bzoj 1176 [Balkan2007]Mokia - CDQ分治 - 树状数组
- BZOJ 1176 && BZOJ 2683 CDQ分治
- BZOJ 2683 CDQ分治
- 【bzoj4285】使者 CDQ分治+扫描线+树状数组