BZOJ 2716/2648 SJY摆棋子 (三维偏序CDQ+树状数组)

题目大意:

洛谷传送门

这明明是一道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
",a[i].ans);
76     return 0;
77 }
原文地址:https://www.cnblogs.com/guapisolo/p/10211320.html