洛谷P4169 天使玩偶 CDQ分治
还是照着CDQ的思路来。
但是有一些改动:
- 要求4个方向的,但是可爱的CDQ分治只能求在自己一个角落方向上的。怎么办?旋转!做4次就好了。
- 统计的不是和,而是——max!理由如下:
设当前点是(x,y),目标点是(x',y'),那么所求的|x-x'|+|y-y'|首先用旋转大法化为x-x'+y-y',然后我们发现这个东西其实就是x+y-x'-y'=(x+y)-(x'+y'),而x+y我们是已知的。所以我们求一下max(x'+y')即可。具体实现是对树状数组魔改。
然后交上去发现狂T不止...
疯狂优化!首先把树状数组的max从作死的M改成了所有坐标中最大的mm,发现不行,跑去看题解。
发现不能每次sort,而且还要删点。
然后学习了一波操作之后,成功的到达了91分...还是有3个点死活过不了。把题解拿下来一交,发现居然也T了一个点,哈哈哈。
听从雨菲的建议,果断开O2,A了。
看代码理解删点优化和魔改树状数组。
1 // luogu-judger-enable-o2 2 #include <cstdio> 3 #include <algorithm> 4 using namespace std; 5 const int M = 1000009,N = 600010,INF=0x3f3f3f3f; 6 inline int read() 7 { 8 int ans=0;char ch=getchar(); 9 while(ch<'0'||ch>'9') ch=getchar(); 10 while(ch>='0'&&ch<='9') ans=(ans<<3)+(ans<<1)+ch-'0',ch=getchar(); 11 return ans; 12 } 13 inline int lowbit(int x){return x&(-x);} 14 int ta[M+1],n,mm,ans[N];int p,rx,ry; 15 inline void add(int x,int a) 16 { 17 if(x<=0) return; 18 for(int i=x;i<=ry;i+=lowbit(i)) ta[i]=max(ta[i],a); 19 return; 20 } 21 inline int getsum(int x) 22 { 23 if(x<=0)return 0;int ans=-INF; 24 for(int i=x;i>0;i-=lowbit(i)) ans=max(ans,ta[i]); 25 return ans; 26 } 27 inline void del(int x) 28 { 29 if(x<=0) return; 30 for(int i=x;i<=ry;i+=lowbit(i)) ta[i]=-INF; 31 return; 32 } 33 struct Node 34 { 35 int x,y,k=-INF,t,type; 36 }node[N],temp[N],f[N]; 37 inline bool cmp_t(Node a,Node b){return a.t<b.t;} 38 inline void rotate() 39 { 40 for(int i=1;i<=n;i++) 41 { 42 int t=f[i].x; 43 f[i].x=mm-f[i].y; 44 f[i].y=t; 45 } 46 return; 47 } 48 void CDQ(int l,int r) 49 { 50 if(l==r) return; 51 int mid=(l+r)>>1; 52 CDQ(l,mid);CDQ(mid+1,r); 53 int i=l,j=mid+1,t=0; 54 while(i<=mid||j<=r) 55 { 56 if(j>r||(i<=mid&&node[i].x<=node[j].x)) 57 { 58 if(node[i].type==1) add(node[i].y,node[i].x+node[i].y); 59 temp[++t]=node[i++]; 60 } 61 else 62 { 63 if(node[j].type>1) {node[j].k=max(node[j].k,getsum(node[j].y)); 64 ans[node[j].t]=min(ans[node[j].t],node[j].x+node[j].y-node[j].k);} 65 ///if(node[j].type>1) node[j].k=min(node[j].k,(node[j].x+node[j].y-getsum(node[j].y))); 66 temp[++t]=node[j++]; 67 } 68 } 69 t=0; 70 for(j=l;j<i;j++) if(node[j].type==1) del(node[j].y); 71 for(i=l;i<=r;i++) node[i]=temp[++t]; 72 return; 73 } 74 75 inline void Delete() 76 { 77 rx=ry=p=0; 78 for(int i=1;i<=n;i++) if(f[i].type==2) rx=max(rx,f[i].x),ry=max(ry,f[i].y); 79 for(int i=1;i<=n;i++) if(f[i].x<=rx&&f[i].y<=ry) node[++p]=f[i]; 80 return; 81 } 82 int main() 83 { 84 fill(ta,ta+M,-INF); 85 int n2=read(),n3=read(),x,y,flag; 86 for(int i=1;i<=n2;i++) 87 { 88 x=read()+1;y=read()+1; 89 f[++n].x=x; 90 f[n].y=y; 91 f[n].type=1; 92 f[n].t=n; 93 mm=max(mm,x); 94 mm=max(mm,y); 95 } 96 for(int i=1;i<=n3;i++) 97 { 98 flag=read();x=read()+1;y=read()+1; 99 f[++n].x=x; 100 f[n].y=y; 101 f[n].type=flag; 102 f[n].t=n; 103 mm=max(mm,x); 104 mm=max(mm,y); 105 } 106 mm++; 107 fill(ans+1,ans+n+1,INF); 108 for(y=1;y<=4;y++) 109 { 110 Delete(); 111 ry++; 112 //for(int i=1;i<=p;i++) printf("%d %d %d\n",node[i].type,node[i].x,node[i].y); 113 CDQ(1,p); 114 //for(int i=1;i<=n;i++)if(f[i].type==2)printf("%d ",ans[i]); 115 //printf("\n"); 116 rotate(); 117 } 118 119 for(int i=1;i<=n;i++) 120 { 121 if(f[i].type==2) printf("%d\n",ans[i]); 122 } 123 124 return 0; 125 } 126 /** 127 1 3 128 3 1 129 2 5 5 130 1 6 4 131 2 5 5 132 */