1. 程式人生 > >cdq分治入門--BZOJ1176: [Balkan2007]Mokia

cdq分治入門--BZOJ1176: [Balkan2007]Mokia

。。 入門 矩形 ++ bzoj == img != void

對w*w,w<=2000000的矩形,一開始全是0(或一開始全是s),n<=170000個操作,每次操作:矩陣內某點加上一個數,查某一個子矩陣的和,保證修改數<=160000,詢問數<=10000。

這還是一個比較明顯的三維偏序:時間維,以及x和y。由於現在時間維是一個Ti<Tj,而x和y是要查x1<=x<=x2,y1<=y<=y2,查一個範圍答案在歸並排序直接查不方便,所以一個詢問拆4個,就變成普通的三維偏序了。

技術分享圖片
 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<stdlib.h>
 4
#include<algorithm> 5 //#include<iostream> 6 using namespace std; 7 8 int n,m,s; 9 #define maxn 300011 10 #define maxm 2000011 11 struct Point 12 { 13 int x,y,v;bool type; 14 //type=1:Q type=0:A 15 }a[maxn]; 16 int ans[maxn]; 17 18 struct BIT 19 { 20 int a[maxm],n; 21 void clear(int
m) {n=m;memset(a,0,sizeof(a));} 22 void add(int x,int v) {for (;x<=n;x+=x&-x) a[x]+=v;} 23 int query(int x) {int ans=0;for (;x;x-=x&-x) ans+=a[x];return ans;} 24 }t; 25 26 int ord[maxn],tmpord[maxn]; 27 void solve(int L,int R) 28 { 29 if (L==R) {ord[L]=L;return;} 30 const int
mid=(L+R)>>1; 31 solve(L,mid); 32 solve(mid+1,R); 33 int i=L,j=mid+1,k=L; 34 while (i<=mid && j<=R) 35 { 36 if (a[ord[i]].x<=a[ord[j]].x) 37 { 38 if (a[ord[i]].type==0) 39 t.add(a[ord[i]].y,a[ord[i]].v); 40 tmpord[k++]=ord[i++]; 41 } 42 else 43 { 44 if (a[ord[j]].type) 45 ans[ord[j]]+=t.query(a[ord[j]].y); 46 tmpord[k++]=ord[j++]; 47 } 48 } 49 for (;j<=R;j++) 50 { 51 if (a[ord[j]].type) ans[ord[j]]+=t.query(a[ord[j]].y); 52 tmpord[k++]=ord[j]; 53 } 54 for (int ii=L;ii<i;ii++) if (!a[ord[ii]].type) t.add(a[ord[ii]].y,-a[ord[ii]].v); 55 for (;i<=mid;i++) tmpord[k++]=ord[i]; 56 for (int x=L;x<=R;x++) ord[x]=tmpord[x]; 57 } 58 59 int main() 60 { 61 scanf("%d%d",&s,&m); 62 t.clear(m); 63 n=0; 64 int op,x,y,z,w; 65 while (scanf("%d",&op) && op!=3) 66 { 67 if (op-1) 68 { 69 scanf("%d%d%d%d",&x,&y,&z,&w); 70 a[++n]=(Point){x-1,y-1,1,1}; 71 a[++n]=(Point){x-1,w,-1,1}; 72 a[++n]=(Point){z,y-1,-1,1}; 73 a[++n]=(Point){z,w,1,1}; 74 } 75 else 76 { 77 scanf("%d%d%d",&x,&y,&z); 78 a[++n]=(Point){x,y,z,0}; 79 } 80 } 81 solve(1,n); 82 83 for (int i=1;i<=n;i++) if (a[i].type) 84 { 85 int Ans=0; 86 for (int to=i+4;i<to;i++) Ans+=ans[i]*a[i].v; 87 i--; 88 printf("%d\n",Ans); 89 } 90 return 0; 91 }
View Code

這題面的s沒有用,怎麽題面也不改。。

cdq分治入門--BZOJ1176: [Balkan2007]Mokia