之前听大神讲过CDQ分治大概是个什么东西,但是一直还没有真正去搞过。今天稍微看了一下,写点自己的理解。
首先CDQ分治有两个条件。
条件1:可以分成两个独立互不影响的问题(这里的“独立”是指将前面区间的影响处理掉后,后面与前面都成为了新的相同问题)
条件2:允许离线(据说最近流行强制在线。。。如果这样只好去写恶心的数据结构了)。
CDQ分治在可以使用的情况下很多高级数据结构题可以用CDQ分治干过去,不仅时空优越而且易于调试(虽然我并不觉得很好调试
大体思路是将问题不断分成两个子问题,用前一个子问题中的修改操作去更新后一个子问题,这样之后就得到了两个互不影响的子问题,达到分治的目的。
贴一道版题代码:BZOJ 1176
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define lowbit(x) ((x)&-(x)) 4 struct data{ 5 int v,x,y,d,f,pos; 6 bool operator <(const data& w)const{ 7 if(x!=w.x) return x<w.x; 8 if(y!=w.y) return y<w.y; 9 return pos<w.pos; 10 } 11 }a[200005],tmp[200005]; 12 int s,w,t[2000005],cnt,ans[200005]; 13 int read(int& x){ 14 x=0; int f=1,a=getchar(); 15 while(a<'0' || a>'9') {if(a=='-') f=-1; a=getchar();} 16 while(a>='0' && a<='9') x=x*10+a-'0',a=getchar(); x*=f; 17 } 18 inline void add(int y,int x){for(int i=y;i<=w;i+=lowbit(i)) t[i]+=x;} 19 inline int query(int y){int ret=0; for(int i=y;i;i-=lowbit(i)) ret+=t[i]; return ret;} 20 void CDQ(int l,int r){ 21 if(l==r) return; 22 int mid=(l+r)>>1,t1=l-1,t2=mid; //这里写错调了老半天 23 for(int i=l;i<=r;i++){ 24 if(a[i].v<=mid && !a[i].pos) add(a[i].y,a[i].d); 25 if(a[i].v>mid && a[i].pos) ans[a[i].pos]+=query(a[i].y)*a[i].f; 26 } 27 for(int i=l;i<=r;i++) 28 if(a[i].v<=mid && !a[i].pos) add(a[i].y,-a[i].d); 29 for(int i=l;i<=r;i++) 30 if(a[i].v<=mid) tmp[++t1]=a[i]; 31 else tmp[++t2]=a[i]; 32 for(int i=l;i<=r;i++) a[i]=tmp[i]; 33 CDQ(l,mid); CDQ(mid+1,r); 34 } 35 int main(){ 36 read(s); read(w); int t,x,y,d,x1,x2,y1,y2; 37 while(1){ 38 read(t); 39 if(t==1){ 40 read(x); read(y); read(d); 41 a[++cnt]=(data){cnt,x,y,d,1,0}; 42 }else if(t==2){ 43 read(x1); read(y1); read(x2); read(y2); ++ans[0]; 44 a[++cnt]=(data){cnt,x1-1,y1-1,0,1,ans[0]}; 45 a[++cnt]=(data){cnt,x2,y2,0,1,ans[0]}; 46 a[++cnt]=(data){cnt,x1-1,y2,0,-1,ans[0]}; 47 a[++cnt]=(data){cnt,x2,y1-1,0,-1,ans[0]}; 48 }else break; 49 } 50 sort(a+1,a+1+cnt); 51 CDQ(1,cnt); 52 for(int i=1;i<=ans[0];i++) 53 printf("%d ",ans[i]); 54 return 0; 55 }