题目描述

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理解还是太浅了……

 //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+树状数组)的更多相关文章

  1. BZOJ 2716: [Violet 3]天使玩偶( CDQ分治 + 树状数组 )

    先cdq分治, 然后要处理点对答案的贡献, 可以以询问点为中心分成4个区域, 然后去掉绝对值(4种情况讨论), 用BIT维护就行了. --------------------------------- ...

  2. BZOJ 2716 [Violet 3]天使玩偶 (CDQ分治、树状数组)

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=2716 怎么KD树跑得都那么快啊..我写的CDQ分治被暴虐 做四遍CDQ分治,每次求一个 ...

  3. BZOJ 2716 Violet 3 天使玩偶 CDQ分治

    题目大意:初始给定平面上的一个点集.提供两种操作: 1.将一个点增加点集 2.查询距离一个点最小的曼哈顿距离 K-D树是啥...不会写... 我仅仅会CDQ分治 对于一个询问,查询的点与这个点的位置关 ...

  4. BZOJ 2716: [Violet 3]天使玩偶

    2716: [Violet 3]天使玩偶 Time Limit: 80 Sec  Memory Limit: 128 MBSubmit: 1473  Solved: 621[Submit][Statu ...

  5. bzoj 2716 [Violet 3]天使玩偶 【CDQ分治】

     KD-tree可做,但是我不会暂时不考虑 大意:在二维平面内,给定n个点,m个操作.操作A:加入一个点:操作B:询问一个点与平面上加入的点的最近距离 不封装会T不封装会T不封装会T不封装会T不封装会 ...

  6. BZOJ 1176/2683 Mokia (三维偏序CDQ+树状数组)

    题目大意: 洛谷传送门 三维偏序裸题.. 每次操作都看成一个三元组$<x,y,t>$,表示$x,y$坐标和操作时间$t $ 询问操作拆成$4$个容斥 接下来就是$CDQ$了,外层按t排序, ...

  7. bzoj 2716 [Violet 3]天使玩偶——KDtree

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2716 第三道KDtree!仍旧是模板.还有CDQ分治做法,见下面. 数组迷之开大?(开6e5 ...

  8. BZOJ 2716 [Violet 3]天使玩偶 ——KD-Tree

    [题目分析] KD-Tree的例题.同BZOJ2648. [代码] #include <cstdio> #include <cstring> #include <cstd ...

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

    2648: SJY摆棋子&&2716: [Violet 3]天使玩偶 Time Limit: 20 Sec  Memory Limit: 128 MB Description 这天,S ...

  10. [BZOJ2716] [Violet 3]天使玩偶(CDQ分治)

    [BZOJ2716] [Violet 3]天使玩偶(CDQ分治) 题面 Ayu 在七年前曾经收到过一个天使玩偶,当时她把它当作时间囊埋在了地下.而七年后 的今天,Ayu 却忘了她把天使玩偶埋在了哪里, ...

随机推荐

  1. 解决CentOS内网机通过Windows下架设代理来访问网络

    新分配的CentOS运行在内网环境下,无法连接Internet,为了能够使用yum部署OpenVas工具,需要在内网下一台Windows主机架设代理,作代理服务器来令虚拟机上网. 代理服务器选择了CC ...

  2. String对象不可改变的特性及内存机制

    JAVA中字符串类型String是不允许改变其内容的,下列语句是如何运行的:String s=new String("ABCD");s=s+"123": 最佳回 ...

  3. 41. First Missing Positive (HashTable)

    Given an unsorted integer array, find the first missing positive integer. For example,Given [1,2,0]  ...

  4. 6-Collision-hdu5114(小球碰撞)

    Collision Time Limit: 15000/15000 MS (Java/Others)    Memory Limit: 512000/512000 K (Java/Others)Tot ...

  5. DSO(dsoframer)的接口文档

    (开发环境)使用前先注册一下DSOFramer.ocx    操作:将DSOFramer.ocx复制到C:\windows\system32目录下,         开始->运行->reg ...

  6. 整理Javascript基础数据和引用数据复制值的问题

    Javascript数据分为两大类:1.基础类型(原始类型数据) 2.引用类型.他们的存储方式是不同的 基础类型的数据存储是保存在栈内存中的: 例如: var a=1; var b=a; var a= ...

  7. SpringMVC源码解析- HandlerAdapter - ModelFactory

    ModelFactory主要是两个职责: 1. 初始化model 2. 处理器执行后将modle中相应参数设置到SessionAttributes中 我们来看看具体的处理逻辑(直接充当分析目录): 1 ...

  8. linux每天一小步---cat命令详解

    1 命令功能 cat命令是linux系统下的一个文本输出命令,通常用于查看文件的内容. 2 命令语法 cat  [选项参数]  文件名 3 命令参数 -n  由1开始对所有输出的内容行数编号 -b   ...

  9. [编译,报错以及其他] 有关C/C++中int不能用-2147483648当最小值的问题

    这个取决于今早看耗子叔的微博: 这里说到了int的取值范围的问题,int的取值是-2147483648 ~ 2147483647,但是如果直接在编译器(VS2013)中使用-2147483648会报错 ...

  10. Android-自定义联系人快速索引

    效果图: 布局去指定 view.custom.shangguigucustomview.MyCustomIndexView 自定义View对象 <!-- 自定义联系人快速索引 --> &l ...