【bzoj 2716】[Violet 3]天使玩偶 (CDQ+树状数组)
题目描述
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
题解
先膜一发大佬
据说这题正解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理解还是太浅了……
//minamoto
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[<<],*p1=buf,*p2=buf;
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,:;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,:;}
inline int read(){
#define num ch-'0'
char ch;bool flag=;int res;
while(!isdigit(ch=getc()))
(ch=='-')&&(flag=true);
for(res=num;isdigit(ch=getc());res=res*+num);
(flag)&&(res=-res);
#undef num
return res;
}
char sr[<<],z[];int C=-,Z;
inline void Ot(){fwrite(sr,,C+,stdout),C=-;}
inline void print(int x){
if(C><<)Ot();if(x<)sr[++C]=,x=-x;
while(z[++Z]=x%+,x/=);
while(sr[++C]=z[Z],--Z);sr[++C]='\n';
}
const int N=1e6+,inf=0x3f3f3f3f;
int n,m,lx,ly,rx,ry,c[N],ans[N];
inline void clear(int x){
for(int i=x;i<=ly;i+=i&-i)
if(c[i]) c[i]=;else break;
}
inline void add(int x,int val){
for(int i=x;i<=ly;i+=i&-i)
cmax(c[i],val);
}
inline int query(int x){
int res=;
for(int i=x;i;i-=i&-i)
cmax(res,c[i]);
return res;
}
struct node{
int x,y,t;bool f;
node(){}
node(const int &x,const int &y,const int &t,const int &f):
x(x),y(y),t(t),f(f){}
inline bool operator <(const node &b)const
{return x<b.x||(x==b.x&&y<b.y);}
}a[N],p[N],q[N];
void CDQ(int l,int r){
if(l==r) return;
int mid=(l+r)>>;
CDQ(l,mid),CDQ(mid+,r);
int j=l;
for(int i=mid+;i<=r;++i)
if(!p[i].f){
while(j<=mid&&p[j].x<=p[i].x){if(p[j].f) add(p[j].y,p[j].x+p[j].y);++j;}
int tmp=query(p[i].y);
if(tmp) tmp=p[i].x+p[i].y-tmp,cmin(ans[p[i].t],tmp);
}
for(int i=l;i<j;++i)
if(p[i].f) clear(p[i].y);
merge(p+l,p+mid+,p+mid+,p+r+,q+l);
memcpy(p+l,q+l,sizeof(node)*(r-l+));
}
void check(){
rx=ry=m=;
for(int i=;i<=n;++i)
if(!p[i].f) cmax(rx,p[i].x),cmax(ry,p[i].y);
for(int i=;i<=n;++i)
if(p[i].x<=rx&&p[i].y<=ry) q[++m]=p[i];
memcpy(p+,q+,sizeof(node)*m);
}
int main(){
//freopen("testdata.in","r",stdin);
n=read(),m=read();
for(int i=;i<=n;++i){
int x=read()+,y=read()+;
p[i]=(node){x,y,i,true};
cmax(lx,x),cmax(ly,y);
}
while(m--){
int k=read(),x=read()+,y=read()+;
++n,p[n]=node(x,y,n,k&);
cmax(lx,x),cmax(ly,y);
}
memcpy(a+,p+,sizeof(node)*n);
memset(ans,inf,sizeof(ans));
check(),CDQ(,m);
for(int i=;i<=n;++i)
p[i]=a[i],p[i].x=lx-p[i].x+;
check(),CDQ(,m);
for(int i=;i<=n;++i)
p[i]=a[i],p[i].y=ly-p[i].y+;
check(),CDQ(,m);
for(int i=;i<=n;++i)
p[i]=a[i],p[i].y=ly-p[i].y+,p[i].x=lx-p[i].x+;
check(),CDQ(,m);
for(int i=;i<=n;++i)
if(!a[i].f) print(ans[i]);
Ot();
return ;
}
【bzoj 2716】[Violet 3]天使玩偶 (CDQ+树状数组)的更多相关文章
- BZOJ 2716: [Violet 3]天使玩偶( CDQ分治 + 树状数组 )
先cdq分治, 然后要处理点对答案的贡献, 可以以询问点为中心分成4个区域, 然后去掉绝对值(4种情况讨论), 用BIT维护就行了. --------------------------------- ...
- BZOJ 2716 [Violet 3]天使玩偶 (CDQ分治、树状数组)
题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=2716 怎么KD树跑得都那么快啊..我写的CDQ分治被暴虐 做四遍CDQ分治,每次求一个 ...
- BZOJ 2716 Violet 3 天使玩偶 CDQ分治
题目大意:初始给定平面上的一个点集.提供两种操作: 1.将一个点增加点集 2.查询距离一个点最小的曼哈顿距离 K-D树是啥...不会写... 我仅仅会CDQ分治 对于一个询问,查询的点与这个点的位置关 ...
- BZOJ 2716: [Violet 3]天使玩偶
2716: [Violet 3]天使玩偶 Time Limit: 80 Sec Memory Limit: 128 MBSubmit: 1473 Solved: 621[Submit][Statu ...
- bzoj 2716 [Violet 3]天使玩偶 【CDQ分治】
KD-tree可做,但是我不会暂时不考虑 大意:在二维平面内,给定n个点,m个操作.操作A:加入一个点:操作B:询问一个点与平面上加入的点的最近距离 不封装会T不封装会T不封装会T不封装会T不封装会 ...
- BZOJ 1176/2683 Mokia (三维偏序CDQ+树状数组)
题目大意: 洛谷传送门 三维偏序裸题.. 每次操作都看成一个三元组$<x,y,t>$,表示$x,y$坐标和操作时间$t $ 询问操作拆成$4$个容斥 接下来就是$CDQ$了,外层按t排序, ...
- bzoj 2716 [Violet 3]天使玩偶——KDtree
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2716 第三道KDtree!仍旧是模板.还有CDQ分治做法,见下面. 数组迷之开大?(开6e5 ...
- BZOJ 2716 [Violet 3]天使玩偶 ——KD-Tree
[题目分析] KD-Tree的例题.同BZOJ2648. [代码] #include <cstdio> #include <cstring> #include <cstd ...
- bzoj 2648: SJY摆棋子&&2716: [Violet 3]天使玩偶 --kdtree
2648: SJY摆棋子&&2716: [Violet 3]天使玩偶 Time Limit: 20 Sec Memory Limit: 128 MB Description 这天,S ...
- [BZOJ2716] [Violet 3]天使玩偶(CDQ分治)
[BZOJ2716] [Violet 3]天使玩偶(CDQ分治) 题面 Ayu 在七年前曾经收到过一个天使玩偶,当时她把它当作时间囊埋在了地下.而七年后 的今天,Ayu 却忘了她把天使玩偶埋在了哪里, ...
随机推荐
- OpenGL 4.0的Tessellation Shader(细分曲面着色器)
细分曲面着色器(Tessellation Shader)处于顶点着色器阶段的下一个阶段,我们可以看以下链接的OpenGL渲染流水线的图:https://www.opengl.org/wiki/Rend ...
- Redis OBJECT命令
[Redis OBJECT命令] 1.OBJECT subcommand [arguments [arguments]] OBJECT 命令允许从内部察看给定 key 的 Redis 对象. 它通常用 ...
- LevelDB Log文件
[LevelDB Log文件] log文件在LevelDb中的主要作用是系统故障恢复时,能够保证不会丢失数据.因为在将记录写入内存的Memtable之前,会先写入Log文件,这样即使系统发生故障,Me ...
- How to Get Vertical Line from Point and Line
Description How to get vertical line cross one point which out of line in line. QPoint Line::Vertica ...
- Basic4android v3.50 发布
这次发布的主要是debug 的增强.说实话,在这一方面B4a 比delphi做的要好.希望delphi 在新的版本里面 能进一步加强. I'm happy to release Basic4andro ...
- pv和pvc状态
原文地址:https://kubernetes.cn/topics/46 API Server 和 PVController API Server: 这个组件提供对API的支持,响应REST操作,验证 ...
- arean.c
glibc-2.14中的arean.c源代码,供研究malloc和free实现使用: /* Malloc implementation for multiple threads without loc ...
- swift -pop的简单动画
//1.新建空文件 命名Podfile //2.写入 pod ‘pop’,’~>1.0’ 保存 //3.打开终端,进入项目路径 执行pod install //4.新建桥接头文件 导入#im ...
- c++ vector反转reverse
template <class BidirectionalIterator> void reverse ( BidirectionalIterator first, Bidirection ...
- Oracle EBS不能正常启动的解决方案 > Jinitiator 乱码
问题1:使用IE浏览器(IE6 IE7 IE8)可以登录EBS,但在打开EBS的WIN Form界面里,IE自动关闭或报错,或是卡住不动 原因1: oracle EBS自带安装的JInitiator ...