这点东西前前后后拖了好几个星期才学会……还是自己太菜啊。
Cdq分治的思想是:把问题序列分割成左右两个,先单独处理左边,再处理左边对右边的影响,再单独处理右边。这样可以消去数据结构上的一个log,降低编码复杂度。
整体二分:当一个询问的答案满足二分性质时,我们可以按照答案的大小分割整个查询和修改序列。每次把序列分成互不相同的两部分。这样能把数据结构的二分拿出来,降低编码复杂度。
说白了,就是当你懒得写树套树或者惨遭卡内存时候的骗分办法。
好了,上例题吧:
BZOJ2683:
二维单点加,矩形查。可以kdtree或树套树水过。
然而这里要用cdq分治。我们把一个查询利用二维前缀和原理拆成4个,然后按x排序,对t(时间)cdq分治,用树状数组维护y上的前缀和。我们先处理t在左边对右边查询的影响,然后再递归处理左右。
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define debug cout 6 using namespace std; 7 const int maxn=8e5+1e2; 8 9 int n; 10 11 struct BinaryIndexTree { 12 int dat[maxn]; 13 #define lowbit(x) (x&-x) 14 inline void update(int pos,int x) { 15 while( pos < maxn ) { 16 dat[pos] += x , 17 pos += lowbit(pos); 18 } 19 } 20 inline int query(int pos) { 21 int ret = 0; 22 while( pos ) 23 ret += dat[pos] , 24 pos -= lowbit(pos); 25 return ret; 26 } 27 }bit; 28 29 struct QNode { 30 int tpe,x,y,aid,tme,lam; 31 friend bool operator < (const QNode &a,const QNode &b) { 32 if( a.x != b.x ) 33 return a.x < b.x; 34 if( a.y != b.y ) 35 return a.y < b.y; 36 return a.tpe < b.tpe; 37 } 38 }ns[maxn],tp[maxn]; 39 40 int cnt,acn; 41 int ans[maxn]; 42 43 inline void cdq(int l,int r) { 44 if( l == r ) 45 return; 46 const int mid = ( l + r ) >> 1; 47 for(int i=l;i<=r;i++) { 48 if( ns[i].tme <= mid && ns[i].tpe == 1 ) 49 bit.update(ns[i].y,ns[i].lam); 50 if( ns[i].tme > mid && ns[i].tpe == 2 ) 51 ans[ns[i].aid] += ns[i].lam * bit.query(ns[i].y); 52 } 53 for(int i=l;i<=r;i++) 54 if( ns[i].tme <= mid && ns[i].tpe == 1 ) 55 bit.update(ns[i].y,-ns[i].lam); 56 int l1 = l , l2 = mid + 1; 57 for(int i=l;i<=r;i++) 58 if( ns[i].tme <= mid ) 59 tp[l1++] = ns[i]; 60 else 61 tp[l2++] = ns[i]; 62 for(int i=l;i<=r;i++) 63 ns[i] = tp[i]; 64 cdq(l,mid); 65 cdq(mid+1,r); 66 } 67 68 int main() { 69 static int t,x,y,xx,yy,lam; 70 scanf("%d",&n); 71 while( scanf("%d",&t) == 1 && t != 3 ) { 72 if( t == 1 ) { 73 scanf("%d%d%d",&x,&y,&lam); 74 ns[++cnt].tpe = t , ns[cnt].x = x , ns[cnt].y = y , 75 ns[cnt].lam = lam , ns[cnt].tme = cnt; 76 } 77 else { 78 scanf("%d%d%d%d",&x,&y,&xx,&yy); 79 --x , --y , ++acn; 80 ns[++cnt].tpe = t , ns[cnt].x = x , ns[cnt].y = y , 81 ns[cnt].aid = acn , ns[cnt].tme = cnt , ns[cnt].lam = 1; 82 ns[++cnt].tpe = t , ns[cnt].x = xx , ns[cnt].y = yy , 83 ns[cnt].aid = acn , ns[cnt].tme = cnt , ns[cnt].lam = 1; 84 ns[++cnt].tpe = t , ns[cnt].x = x , ns[cnt].y = yy , 85 ns[cnt].aid = acn , ns[cnt].tme = cnt , ns[cnt].lam = -1; 86 ns[++cnt].tpe = t , ns[cnt].x = xx , ns[cnt].y = y , 87 ns[cnt].aid = acn , ns[cnt].tme = cnt , ns[cnt].lam = -1; 88 } 89 } 90 sort(ns+1,ns+1+cnt); 91 cdq(1,cnt); 92 93 for(int i=1;i<=acn;i++) 94 printf("%d\n",ans[i]); 95 96 return 0; 97 }