题目描述

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. SpringMVC @RequestBody请求参数在postman中的请求

    使用SpringMVC框架,controller使用参数  @RequestBody  LoginReq req   注解方式模拟http请求 需要请求header添加一个参数 设置  Header参 ...

  2. PatBlt

    PatBlt     该函数使用当前选入指定设备环境中的刷子绘制给定的矩形区域.通过使用给出的光栅操作来对该刷子的像素和表面像素进行组合. 原型: BOOL PatBlt(     HDC hdc,  ...

  3. mongoTemplate.aggregate()聚合查询

    一.概述 1. 聚合的表达式 MongoDB中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果.有点类似sql语句中的 count(*). 下表展示了一些聚 ...

  4. rook 删不掉的问题

    # kubectl get crd -o yamlapiVersion: v1items:- apiVersion: apiextensions.k8s.io/v1beta1  kind: Custo ...

  5. Python与Go快速排序

    #!/usr/bin/env python # -*- coding: utf-8 -*- # 快速排序 # 时间复杂度 O(n lgn)-- O(n^2) def quick_sort(array) ...

  6. Shrio03 Authenticator、配置多个Realm、SecurityManager认证策略

    1 Authenticator 简介 1.1 层次结构图 1.2 作用 职责是验证用户帐号,是ShiroAPI中身份验证核心的入口点:接口中声明的authenticate方法就是用来实现认证逻辑的. ...

  7. 怎样查看lInux系统中的所有运行进程

    可以使用ps命令.它能显示当前运行中进程的相关信息,包括进程的PID.Linux和UNIX都支持ps命令,显示所有运行中进程的相关信息. ps命令能提供一份当前进程的快照.如果想状态可以自动刷新,可以 ...

  8. Python爬虫进阶五之多线程的用法

    前言 我们之前写的爬虫都是单个线程的?这怎么够?一旦一个地方卡到不动了,那不就永远等待下去了?为此我们可以使用多线程或者多进程来处理. 首先声明一点! 多线程和多进程是不一样的!一个是 thread ...

  9. for(var i=0;i<5;i++){ setTimeout(function() { console.log(i) }, 100);}

    涉及异步.作用域.闭包 1.settimeout是异步执行,100ms后往任务队列里面添加一个任务 2.let不仅将i绑定到for循环块中,事实上它将其重新绑定到循环体的每一次迭代中 3.闭包 set ...

  10. msdn 硬盘

    https://msdn.microsoft.com/library/windows/hardware/ff566204 Returns the ATA-2 identify data, the Se ...