久仰cdq(分治)大名,今日才来造访,礼数不周也。。。。。(发个牢骚~)
所谓cdq分治,就是分治所有操作,计算[l,mid]中的修改对[mid+1,r]中的询问的影响。
无法理解的同学可以借助归并排序的思想思考。
抄袭别人讲以上的话吧
1、T(n)=2T(n/2)+O(kn)的解是T(n)=O(kn log n)
2、T(n)=2T(n/2)+O(kn log n)的解是T(n)=O(kn log^2 n)
3、T(n)=2T(n/2)+O(k)的解是T(n)=O(kn)
所以cdq分治的复杂度也可以简单的算出来了。
cdq能处理的题目必须满足:1、允许离线 2、前面的修改对后面的影响很容易算出来
比如说这一题
在[l,mid]部分的修改按x排序从小到大加进一个树状数组里,不断更新对[mid+1,r]的影响。
复杂度就是第二种计算方式,可就是O(q log^2 w)
猥琐的code如下:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define lowbit(x) ((x)&(-(x))) const int Maxn=200000; int x1[Maxn],x2[Maxn],y1[Maxn],y2[Maxn],tr[Maxn]; int a[Maxn],b[Maxn],c[Maxn],k[Maxn],ans[Maxn]; int n,m,s,w,i; struct arr{ int x,l,r,k,c; bool operator <(const arr &a)const { return x<a.x; } } qk[Maxn]; struct ad{ int x,y,w; bool operator <(const ad &a)const { return x<a.x; } } g[Maxn]; int query(int x){ int ret=0; for (int i=x;i>0;i-=lowbit(i)) ret+=tr[i]; return ret; } void ins(int x,int s){ for (int i=x;i<=m;i+=lowbit(i)) tr[i]+=s; } void merge(int l,int r){ if (l==r) return; int mid=(l+r)>>1, t=0, tt=0, i, j; merge(l,mid); for (i=mid+1;i<=r;i++) if (k[i]==2){ qk[++t]=(arr){x1[i]-1, y1[i], y2[i], i, 0}; qk[++t]=(arr){x2[i], y1[i], y2[i], i, 1}; } sort(qk+1,qk+t+1); for (i=l;i<=mid;i++) if (k[i]==1) g[++tt]=(ad){x1[i],y1[i],x2[i]}; sort(g+1,g+tt+1); for (i=1,j=1;i<=tt;i++){ while (j<=t && qk[j].x<g[i].x){ if (qk[j].c==0) ans[qk[j].k]-=query(qk[j].r)-query(qk[j].l-1); else ans[qk[j].k]+=query(qk[j].r)-query(qk[j].l-1); j++; } ins(g[i].y,g[i].w); } while (j<=t){ if (qk[j].c==0) ans[qk[j].k]-=query(qk[j].r)-query(qk[j].l-1); else ans[qk[j].k]+=query(qk[j].r)-query(qk[j].l-1); j++; } for (i=1;i<=tt;i++) ins(g[i].y,-g[i].w); merge(mid+1,r); } int main(){ //freopen("1176.in","r",stdin); //freopen("1176.out","w",stdout); scanf("%d%d",&s,&w); n=1; while (true){ scanf("%d",&k[n]); if (k[n]==0 || k[n]==3) break; if (k[n]==1){ scanf("%d%d%d",&x1[n],&y1[n],&x2[n]); c[++m]=y1[n]; }else if (k[n]==2){ scanf("%d%d%d%d",&x1[n],&y1[n],&x2[n],&y2[n]); ans[n]+=s*(x2[n]-x1[n]+1)*(y2[n]-y1[n]+1); c[++m]=y1[n]; c[++m]=y2[n]; } n++; } sort(c+1,c+m+1); m=unique(c+1,c+m+1)-c-1; for (i=1;i<n;i++){ y1[i]=lower_bound(c+1,c+m+1,y1[i])-c; if (k[i]==2) y2[i]=lower_bound(c+1,c+m+1,y2[i])-c; } merge(1,--n); for (i=1;i<=n;i++) if (k[i]==2) printf("%d\n",ans[i]); return 0; }
cdq分治的精华远不止如此,今后慢慢研习