1. 程式人生 > >BZOJ 2716/2648 SJY擺棋子 (三維偏序CDQ)

BZOJ 2716/2648 SJY擺棋子 (三維偏序CDQ)

ora pro while 三元 %d i++ ext def http

題目大意:

洛谷傳送門

這明明是一道KD-Tree,CDQ分治是TLE的做法

化簡式子,$|x1-x2|-|y1-y2|=(x1+y1)-(x2+y2)$

而$CDQ$分治只能解決$x1 \leq x2,y1 \leq y2$的情況

把每次插入操作都相當於一個三元組$<x,y,t>$,權值是$x+y$。這就是一個三維偏序問題,用樹狀數組維護最大值即可

所以通過坐標變換,跑$4$次$CDQ$就行了?

沒錯,你會像我一樣T得飛起

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4
#define N1 1001000 5 #define M1 1001000 6 #define ll long long 7 #define dd double 8 #define inf 233333333 9 using namespace std; 10 11 int gint() 12 { 13 int ret=0,fh=1;char c=getchar(); 14 while(c<0||c>9){if(c==-)fh=-1;c=getchar();} 15 while(c>=0&&c<=9
){ret=ret*10+c-0;c=getchar();} 16 return ret*fh; 17 } 18 int n,m,ma,nm,mx,my; 19 struct BIT{ 20 int ma[M1]; 21 void update(int x,int w){ for(int i=x;i<=my;i+=(i&(-i))) ma[i]=max(ma[i],w); } 22 int query(int x){ int ans=-inf; for(int i=x;i;i-=(i&(-i))) ans=max(ans,ma[i]); return ans; }
23 void clr(int x){ for(int i=x;i<=my;i+=(i&(-i))) ma[i]=-inf;} 24 void init(){ for(int i=1;i<=my;i++) ma[i]=-inf; } 25 }s; 26 struct node{int x,y,p,t,ans;}a[N1],tmp[N1]; 27 int cmp1(node s1,node s2){ if(s1.x!=s2.x) return s1.x<s2.x; if(s1.y!=s2.y) return s1.y<s2.y; return s1.p<s2.p;} 28 int cmpt(node s1,node s2){ return s1.t<s2.t; } 29 int que[N1],tl; 30 31 void CDQ(int L,int R) 32 { 33 if(R-L<=1) return; 34 int i,j,k,M=(L+R)>>1; 35 for(i=L,j=M,k=L;k<R;k++) 36 { 37 if(a[k].t<M) tmp[i++]=a[k]; 38 else tmp[j++]=a[k]; 39 } 40 for(k=L;k<R;k++) a[k]=tmp[k]; 41 CDQ(L,M); 42 for(i=L,j=M;i<M&&j<R;) 43 { 44 if(cmp1(a[i],a[j])){ if(a[i].p==1) { s.update(a[i].y,a[i].x+a[i].y); que[++tl]=i; } i++; } 45 else{ if(a[j].p==2) a[j].ans=min(a[j].ans,(a[j].x+a[j].y)-s.query(a[j].y)); j++; } 46 } 47 while(j<R){ if(a[j].p==2) a[j].ans=min(a[j].ans,(a[j].x+a[j].y)-s.query(a[j].y)); j++; } 48 while(tl){ s.clr(a[que[tl--]].y); } 49 CDQ(M,R); 50 for(i=L,j=M,k=0;i<M&&j<R;) 51 { 52 if(cmp1(a[i],a[j])) tmp[++k]=a[i++]; 53 else tmp[++k]=a[j++]; 54 } 55 while(i<M){ tmp[++k]=a[i++]; } 56 while(j<R){ tmp[++k]=a[j++]; } 57 for(k=L;k<R;k++) a[k]=tmp[k-L+1]; 58 } 59 int p[N1]; 60 61 int main() 62 { 63 int i,j; n=gint(); m=gint(); nm=n+m; 64 for(i=1;i<=n;i++){ a[i].p=1; a[i].x=gint()+1; a[i].y=gint()+1; a[i].t=i; a[i].ans=inf; mx=max(mx,a[i].x); my=max(my,a[i].y); } 65 for(i=n+1;i<=n+m;i++){ a[i].p=gint(); a[i].x=gint()+1; a[i].y=gint()+1; a[i].t=i; a[i].ans=inf; mx=max(mx,a[i].x); my=max(my,a[i].y); } 66 sort(a+1,a+nm+1,cmp1); s.init(); 67 CDQ(1,nm+1); 68 for(i=1;i<=nm;i++){ a[i].x=mx-a[i].x+1; } sort(a+1,a+nm+1,cmp1); 69 CDQ(1,nm+1); 70 for(i=1;i<=nm;i++){ a[i].y=my-a[i].y+1; } sort(a+1,a+nm+1,cmp1); 71 CDQ(1,nm+1); 72 for(i=1;i<=nm;i++){ a[i].x=mx-a[i].x+1; } sort(a+1,a+nm+1,cmp1); 73 CDQ(1,nm+1); 74 sort(a+1,a+nm+1,cmpt); 75 for(i=n+1;i<=nm;i++) if(a[i].p==2) printf("%d\n",a[i].ans); 76 return 0; 77 }

BZOJ 2716/2648 SJY擺棋子 (三維偏序CDQ)