【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 却忘了她把天使玩偶埋在了哪里, ...
 
随机推荐
- 解决CentOS内网机通过Windows下架设代理来访问网络
			
新分配的CentOS运行在内网环境下,无法连接Internet,为了能够使用yum部署OpenVas工具,需要在内网下一台Windows主机架设代理,作代理服务器来令虚拟机上网. 代理服务器选择了CC ...
 - String对象不可改变的特性及内存机制
			
JAVA中字符串类型String是不允许改变其内容的,下列语句是如何运行的:String s=new String("ABCD");s=s+"123": 最佳回 ...
 - 41. First Missing Positive (HashTable)
			
Given an unsorted integer array, find the first missing positive integer. For example,Given [1,2,0] ...
 - 6-Collision-hdu5114(小球碰撞)
			
Collision Time Limit: 15000/15000 MS (Java/Others) Memory Limit: 512000/512000 K (Java/Others)Tot ...
 - DSO(dsoframer)的接口文档
			
(开发环境)使用前先注册一下DSOFramer.ocx 操作:将DSOFramer.ocx复制到C:\windows\system32目录下, 开始->运行->reg ...
 - 整理Javascript基础数据和引用数据复制值的问题
			
Javascript数据分为两大类:1.基础类型(原始类型数据) 2.引用类型.他们的存储方式是不同的 基础类型的数据存储是保存在栈内存中的: 例如: var a=1; var b=a; var a= ...
 - SpringMVC源码解析- HandlerAdapter - ModelFactory
			
ModelFactory主要是两个职责: 1. 初始化model 2. 处理器执行后将modle中相应参数设置到SessionAttributes中 我们来看看具体的处理逻辑(直接充当分析目录): 1 ...
 - linux每天一小步---cat命令详解
			
1 命令功能 cat命令是linux系统下的一个文本输出命令,通常用于查看文件的内容. 2 命令语法 cat [选项参数] 文件名 3 命令参数 -n 由1开始对所有输出的内容行数编号 -b ...
 - [编译,报错以及其他] 有关C/C++中int不能用-2147483648当最小值的问题
			
这个取决于今早看耗子叔的微博: 这里说到了int的取值范围的问题,int的取值是-2147483648 ~ 2147483647,但是如果直接在编译器(VS2013)中使用-2147483648会报错 ...
 - Android-自定义联系人快速索引
			
效果图: 布局去指定 view.custom.shangguigucustomview.MyCustomIndexView 自定义View对象 <!-- 自定义联系人快速索引 --> &l ...