博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【bzoj 2716】[Violet 3]天使玩偶 (CDQ+树状数组)
阅读量:7153 次
发布时间:2019-06-29

本文共 2930 字,大约阅读时间需要 9 分钟。

题目描述

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

题解

先膜一发

据说这题正解KD-tree,然而我只会CDQ……还想了半天啥都没想出来……

先假设,所有回忆出来的点都在查询点的左下方,那么距离如下(A为查询点,B为某一个回忆出来的点)

$$Dist(A,B)=|x_A-x_B|+|y_A-y_B|=(x_A+y_A)-(x_B+y_B)$$

因为$x_A+y_A$对同一个查询点来说是一个定值,所以只要找到$x_B+y_B$的最大值,就可以找到$Dist(A,B)$的最小值

于是问题就转化为:对于一个询问$(x,y)$,查找$x_i<=x,y_i<=y$且$i$的时间戳小于当前询问的最大$x_i+y_i$,很明显,这就是一个三维偏序问题,可以用CDQ求解

然而问题是不能保证所有点都在查询点的下方,所以我们要将其他四个方位的点的坐标变换一下。简单来说就是旋转整张图,然后在四个答案里取最小的就好了

所以做四遍CDQ(当初刚看到这句话差点没吓到……)

然后有几个向大佬学习的优化

1.每次CDQ前,把肯定不在左下方的点去掉

2.每一次重新建图很麻烦,直接保留一个原图然后转一下就好了

感觉我对CDQ理解还是太浅了……

1 //minamoto  2 #include
3 #include
4 #include
5 #include
6 using namespace std; 7 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) 8 char buf[1<<21],*p1=buf,*p2=buf; 9 template
inline bool cmax(T&a,const T&b){
return a
inline bool cmin(T&a,const T&b){ return a>b?a=b,1:0;} 11 inline int read(){ 12 #define num ch-'0' 13 char ch;bool flag=0;int res; 14 while(!isdigit(ch=getc())) 15 (ch=='-')&&(flag=true); 16 for(res=num;isdigit(ch=getc());res=res*10+num); 17 (flag)&&(res=-res); 18 #undef num 19 return res; 20 } 21 char sr[1<<21],z[20];int C=-1,Z; 22 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;} 23 inline void print(int x){ 24 if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x; 25 while(z[++Z]=x%10+48,x/=10); 26 while(sr[++C]=z[Z],--Z);sr[++C]='\n'; 27 } 28 const int N=1e6+5,inf=0x3f3f3f3f; 29 int n,m,lx,ly,rx,ry,c[N],ans[N]; 30 inline void clear(int x){ 31 for(int i=x;i<=ly;i+=i&-i) 32 if(c[i]) c[i]=0;else break; 33 } 34 inline void add(int x,int val){ 35 for(int i=x;i<=ly;i+=i&-i) 36 cmax(c[i],val); 37 } 38 inline int query(int x){ 39 int res=0; 40 for(int i=x;i;i-=i&-i) 41 cmax(res,c[i]); 42 return res; 43 } 44 struct node{ 45 int x,y,t;bool f; 46 node(){} 47 node(const int &x,const int &y,const int &t,const int &f): 48 x(x),y(y),t(t),f(f){} 49 inline bool operator <(const node &b)const 50 { return x
>1; 55 CDQ(l,mid),CDQ(mid+1,r); 56 int j=l; 57 for(int i=mid+1;i<=r;++i) 58 if(!p[i].f){ 59 while(j<=mid&&p[j].x<=p[i].x){ if(p[j].f) add(p[j].y,p[j].x+p[j].y);++j;} 60 int tmp=query(p[i].y); 61 if(tmp) tmp=p[i].x+p[i].y-tmp,cmin(ans[p[i].t],tmp); 62 } 63 for(int i=l;i

 

转载于:https://www.cnblogs.com/bztMinamoto/p/9459595.html

你可能感兴趣的文章
软件项目质量保证——编码规范
查看>>
import static和import的区别
查看>>
android中Invalidate和postInvalidate的区别
查看>>
hive load from hdfs出错
查看>>
IOS开发:xcode5版本引发的问题
查看>>
亿级数据时,内存性能低于IO性能
查看>>
asp.net 负载均衡下session存储的解决方法
查看>>
构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(17)-LinQ动态排序
查看>>
Yii框架操作数据库的几种方式与mysql_escape_string
查看>>
Oracle初级性能优化总结
查看>>
Leetcode: Valid Sudoku
查看>>
公有云与私有云的差别(转)
查看>>
解剖SQLSERVER 第十六篇 OrcaMDF RawDatabase --MDF文件的瑞士军刀(译)
查看>>
jQuery插件:jqGrid使用(一)
查看>>
mac显示隐藏文件
查看>>
FastDFS的配置、部署与API使用解读(6)FastDFS配置详解之Storage配置(转)
查看>>
android studio 使用 jni 编译 opencv 完整实例 之 图像边缘检测!从此在andrid中自由使用 图像匹配、识别、检测...
查看>>
学习心得:《十个利用矩阵乘法解决的经典题目》from Matrix67
查看>>
领域驱动开发推荐代码示例 — Microsoft NLayerApp
查看>>
Linux 安装Rsync和配置
查看>>