[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 的询问,在单独的一行内输出该询问的结果。

输入输出样例

输入样例#1: 复制
2 3 
1 1 
2 3 
2 1 2 
1 3 3 
2 4 2
输出样例#1: 复制
1 
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摆棋子的主要内容,如果未能解决你的问题,请参考以下文章

[Violet]天使玩偶/SJY摆棋子

[Violet]天使玩偶/SJY摆棋子

P4169 [Violet]天使玩偶/SJY摆棋子

[Violet]天使玩偶/SJY摆棋子

[Violet]天使玩偶/SJY摆棋子

bzoj 2648: SJY摆棋子&&2716: [Violet 3]天使玩偶 --kdtree