[Violet]天使玩偶/SJY摆棋子
Posted slrslr
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Violet]天使玩偶/SJY摆棋子相关的知识,希望对你有一定的参考价值。
题目背景
感谢@浮尘ii 提供的一组hack数据
题目描述
Ayu 在七年前曾经收到过一个天使玩偶,当时她把它当作时间囊埋在了地下。而七年后 的今天,Ayu 却忘了她把天使玩偶埋在了哪里,所以她决定仅凭一点模糊的记忆来寻找它。
我们把 Ayu 生活的小镇看作一个二维平面坐标系,而 Ayu 会不定时地记起可能在某个点 (xmy) 埋下了天使玩偶;或者 Ayu 会询问你,假如她在 (x,y) ,那么她离近的天使玩偶可能埋下的地方有多远。
因为 Ayu 只会沿着平行坐标轴的方向来行动,所以在这个问题里我们定义两个点之间的距离为dist(A,B)=|Ax-Bx|+|Ay-By|。其中 Ax 表示点 A的横坐标,其余类似。
输入输出格式
输入格式:第一行包含两个整数n和m ,在刚开始时,Ayu 已经知道有n个点可能埋着天使玩偶, 接下来 Ayu 要进行m 次操作
接下来n行,每行两个非负整数 (xi,yi),表示初始n个点的坐标。
再接下来m 行,每行三个非负整数 t,xi,yi。
如果t=1 ,则表示 Ayu 又回忆起了一个可能埋着玩偶的点 (xi,yi) 。
如果t=2 ,则表示 Ayu 询问如果她在点 (xi,yi) ,那么在已经回忆出来的点里,离她近的那个点有多远
输出格式:对于每个t=2 的询问,在单独的一行内输出该询问的结果。
输入输出样例
说明
n,m<=300 000
xi,yi<=1 000 000
慢的一批,开了O2才能过,毕竟自带大常数写法可能还有问题
其实不是特别难想,首先一维时间戳二维x轴三维y轴是能想出来的
我们想办法把三维都弄的有序了才好处理对吧,所以我们应该分成四个方向处理
考虑这个式子dist(A,B)=|Ax-Bx|+|Ay-By|,假如查询点A且其余点都在A的左下方
则dist(A,B)=Ax+Ay-Bx-By|,Bx+By取最大值即可
那么我们就有思路了,对每个方向分别处理,以y为关键字将x+y插进树状数组即可
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define M 1000010 6 using namespace std; 7 8 int n,m,tot,maxx,maxy; 9 int val[M],ans[M]; 10 11 struct point 12 { 13 int x,y,t,opt; 14 }q[M],p[M],tmp[M]; 15 int read() 16 { 17 char c=getchar(); int x=0,f=1; 18 while(c>‘9‘||c<‘0‘) {if(c==‘-‘)f=-1; c=getchar();} 19 while(c>=‘0‘&&c<=‘9‘) {x=x*10+c-‘0‘,c=getchar();} 20 return x*f; 21 } 22 23 inline void change(int loc,int v) {for(int i=loc;i<=maxy;i+=i&(-i)) val[i]=max(val[i],v);} 24 inline int query(int loc) 25 { 26 int ans=0; 27 for(int i=loc;i>0;i-=i&(-i)) ans=max(ans,val[i]); 28 return ans; 29 } 30 inline void clear(int loc) {for(int i=loc;i<=maxy;i+=i&(-i)) val[i]=0;} 31 32 void solve(int l,int r) 33 { 34 if(l==r) return; 35 int mid=(l+r)>>1; 36 solve(l,mid); solve(mid+1,r); 37 int i=l,j=mid+1,k=l; 38 while(i<=mid&&j<=r) 39 { 40 if(q[i].x<=q[j].x) 41 { 42 if(!q[i].opt) change(q[i].y,q[i].x+q[i].y); 43 tmp[k++]=q[i++]; 44 } 45 else 46 { 47 if(q[j].opt) 48 { 49 int res=query(q[j].y); 50 if(res) ans[q[j].t]=min(ans[q[j].t],q[j].x+q[j].y-res); 51 } 52 tmp[k++]=q[j++]; 53 } 54 } 55 while(i<=mid) tmp[k++]=q[i++]; 56 while(j<=r) 57 { 58 if(q[j].opt) 59 { 60 int res=query(q[j].y); 61 if(res) ans[q[j].t]=min(ans[q[j].t],q[j].x+q[j].y-res); 62 } 63 tmp[k++]=q[j++]; 64 } 65 for(int i=l;i<=mid;i++) 66 if(!q[i].opt) 67 clear(q[i].y); 68 for(int i=l;i<=r;i++) q[i]=tmp[i]; 69 } 70 71 void pre() 72 { 73 tot=0; 74 int upx=0,upy=0; 75 for(int i=1;i<=n;i++) 76 if(q[i].opt) 77 { 78 upx=max(upx,q[i].x); 79 upy=max(upy,q[i].y); 80 } 81 for(int i=1;i<=n;i++) 82 if(q[i].x<=upx&&q[i].y<=upy) 83 tmp[++tot]=q[i]; 84 for(int i=1;i<=tot;i++) q[i]=tmp[i]; 85 } 86 87 int main() 88 { 89 n=read(); m=read(); 90 for(int i=1;i<=n;i++) 91 { 92 int x=read()+1,y=read()+1; 93 q[i]=(point){x,y,0,0}; 94 maxx=max(maxx,x); maxy=max(maxy,y); 95 } 96 for(int i=1;i<=m;i++) 97 { 98 int opt=read(),x=read()+1,y=read()+1; 99 q[++n]=(point){x,y,i,opt-1}; 100 maxx=max(maxx,x); maxy=max(maxy,y); 101 } 102 maxx++; maxy++; 103 for(int i=1;i<=n;i++) p[i]=q[i]; 104 memset(ans,0x3f,sizeof(ans)); 105 pre(); solve(1,tot); 106 for(int i=1;i<=n;i++) q[i]=p[i],q[i].x=maxx-p[i].x; 107 pre(); solve(1,tot); 108 for(int i=1;i<=n;i++) q[i]=p[i],q[i].y=maxy-p[i].y; 109 pre(); solve(1,tot); 110 for(int i=1;i<=n;i++) q[i]=p[i],q[i].x=maxx-p[i].x,q[i].y=maxy-p[i].y; 111 pre(); solve(1,tot); 112 for(int i=1;i<=n;i++) 113 if(p[i].opt) 114 printf("%d ",ans[p[i].t]); 115 return 0; 116 }
以上是关于[Violet]天使玩偶/SJY摆棋子的主要内容,如果未能解决你的问题,请参考以下文章