bzoj2716: [Violet 3]天使玩偶
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2716
由于距离定义为曼哈顿距离,我们先将绝对值符号去掉。这时可以分为四种情况,但是我们可以对点的横纵坐标进行一些处理(处理方法可以看程序),可以使四种情况都变为一种:Ax>Bx,Ay>By。这时距离表示为dist(A,B)=(Ax+Ay)-(Bx+By)。对于一个点,我们只需要去找位于它左下方的x+y最大的点就行了。那么问题就变成了一道简单的CDQ分治题。
不过像我这种渣渣,TLE了好几遍,把读入优化和一些小优化加进去才过,哎,太弱了。
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #define inf 4000000 6 #define maxn 1000010 7 using namespace std; 8 int n,m,cnt,tot,pos[maxn],ans[maxn],t[maxn],maxx,maxy; 9 struct fuck{int x,y,id,op;}e[maxn],f[maxn]; 10 int read(){ 11 int x=0,f=1; char ch; 12 for(ch=getchar();ch<'0'||ch>'9';ch=getchar()) if(ch=='-') f=-1; 13 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; 14 return x*f; 15 } 16 void change(int x,int y){for(int i=x;i<=maxy;i+=i&-i) t[i]=max(t[i],y);} 17 int query(int x){int y=0; for(int i=x;i;i-=i&-i) y=max(y,t[i]); return y==0?-inf:y;} 18 bool comp(fuck a,fuck b){return a.x<b.x;} 19 void solve(int l,int r){ 20 if(l==r) return; 21 int mid=(l+r)>>1; 22 solve(l,mid); solve(mid+1,r); 23 sort(f+l,f+mid+1,comp); sort(f+mid+1,f+r+1,comp); 24 int i=l,j=mid+1,last=0; 25 while(j<=r){ 26 while(i<=mid&&f[i].op==2) i++; 27 while(j<=r&&f[j].op==1) j++; 28 if(i<=mid&&f[i].x<=f[j].x) change(f[i].y,f[i].x+f[i].y),last=i++; 29 else if(j<=r) ans[f[j].id]=min(ans[f[j].id],f[j].x+f[j].y-query(f[j].y)),j++; 30 } 31 for(int i=l;i<=last;i++){ 32 if(f[i].op==1) 33 for(int j=f[i].y;j<=maxy;j+=j&-j) t[j]=0; 34 } 35 } 36 int main(){ 37 n=read(); m=read(); 38 for(int i=1;i<=n+m;i++) ans[i]=inf; 39 for(int i=1;i<=n;i++){ 40 e[i].op=1; e[i].id=i; e[i].x=read()+1; e[i].y=read()+1; 41 maxx=max(maxx,e[i].x); maxy=max(maxy,e[i].y); 42 } 43 int type,x,y; 44 for(int i=n+1;i<=n+m;i++){ 45 e[i].op=read(); e[i].id=i; e[i].x=read()+1; e[i].y=read()+1; 46 maxx=max(maxx,e[i].x); maxy=max(maxy,e[i].y); 47 if(e[i].op==2) pos[++cnt]=i; 48 } 49 maxx++; maxy++; tot=n+m; 50 for(int i=1;i<=tot;i++) f[i]=e[i]; solve(1,tot); 51 for(int i=1;i<=tot;i++) f[i]=e[i],f[i].x=maxx-f[i].x; solve(1,tot); 52 for(int i=1;i<=tot;i++) f[i]=e[i],f[i].y=maxy-f[i].y; solve(1,tot); 53 for(int i=1;i<=tot;i++) f[i]=e[i],f[i].x=maxx-f[i].x,f[i].y=maxy-f[i].y; solve(1,tot); 54 for(int i=1;i<=cnt;i++) printf("%d\n",ans[pos[i]]); 55 return 0; 56 }