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
 2 #include
 3 #include
 4 #include
 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 }

 

转载于:https://www.cnblogs.com/longshengblog/p/5511593.html

你可能感兴趣的:(php)