原题

已知n个点有天使玩偶,有m次操作:

操作1:想起来某个位置有一个天使玩偶

操作2:询问离当前点最近的天使玩偶的曼哈顿距离


显然的CDQ问题,三维分别为时间,x轴,y轴。

但是这道题的问题在于最近距离怎么维护。

曼哈顿距离定义为|x2-x1|+|y2-y1|,所以把绝对值展开后一共有四种情况:

\(x2-x1+y2-y1 => x2+y2-(x1+y1)
x1-x2+y2-y1 => -x2+y2+(x1-y1)
x2-x1+y1-y2 => x2-y2+(y1-x1)
x1-x2+y1-y2 => -x2-y2+(x1+y1)\)

所以把四种情况都讨论一遍,每次处理为该情况的点对即可。

#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 500010
using namespace std;
int n,m,op,ans[N],mxy,f[1000010];
struct hhh
{
int x,y,tm,op,num;
bool operator < (const hhh &b) const
{
return tm<b.tm;
}
}p[2*N],tmp[2*N]; int read()
{
int ans=0,fu=1;
char j=getchar();
for (;j<'0' || j>'9';j=getchar()) if (j=='-') fu=-1;
for (;j>='0' && j<='9';j=getchar()) ans*=10,ans+=j-'0';
return ans*fu;
} inline void add(int x,int y)
{
while (x<=mxy) f[x]=max(f[x],y),x+=x&-x;
} inline int query(int x)
{
int ans=0xc0c0c0c0;
while (x) ans=max(ans,f[x]),x-=x&-x;
return ans;
} inline void clear(int x)
{
while (x<=mxy) f[x]=0xc0c0c0c0,x+=x&-x;
} void solve(int l,int r)
{
if (l==r) return ;
int mid=(l+r)>>1;
solve(l,mid);
solve(mid+1,r);
int l1=l,l2=mid+1;
for (int i=l;i<=r;i++)
{
if (l1<=mid && (l2>r || p[l1].x<p[l2].x)) tmp[i]=p[l1++];
else tmp[i]=p[l2++];
} for (int i=l;i<=r;i++)
{
p[i]=tmp[i];
if (p[i].tm>mid && p[i].op) ans[p[i].num]=min(ans[p[i].num],p[i].x+p[i].y-query(p[i].y));
if (p[i].tm<=mid && !p[i].op) add(p[i].y,p[i].x+p[i].y);
}
for (int i=l;i<=r;i++)
{
if (p[i].tm<=mid && !p[i].op)
clear(p[i].y);
} for (int i=l;i<=r;i++)
{
if (p[i].tm>mid && p[i].op) ans[p[i].num]=min(ans[p[i].num],p[i].x-p[i].y-query(mxy-p[i].y));
if (p[i].tm<=mid && !p[i].op) add(mxy-p[i].y,p[i].x-p[i].y);
}
for (int i=l;i<=r;i++)
{
if (p[i].tm<=mid && !p[i].op)
clear(mxy-p[i].y);
} for (int i=r;i>=l;i--)
{
if (p[i].tm>mid && p[i].op) ans[p[i].num]=min(ans[p[i].num],-p[i].x+p[i].y-query(p[i].y));
if (p[i].tm<=mid && !p[i].op) add(p[i].y,p[i].y-p[i].x);
}
for (int i=r;i>=l;i--)
{
if (p[i].tm<=mid && !p[i].op)
clear(p[i].y);
} for (int i=r;i>=l;i--)
{
if (p[i].tm>mid && p[i].op) ans[p[i].num]=min(ans[p[i].num],-p[i].x-p[i].y-query(mxy-p[i].y));
if (p[i].tm<=mid && !p[i].op) add(mxy-p[i].y,-p[i].x-p[i].y);
}
for (int i=r;i>=l;i--)
{
if (p[i].tm<=mid && !p[i].op)
clear(mxy-p[i].y);
}
} int main()
{
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
n=read();
m=read();
for (int i=1;i<=n;i++)
{
p[i].x=read()+1;
p[i].y=read()+1;
p[i].tm=i;
mxy=max(mxy,p[i].y);
}
for (int i=1;i<=m;i++)
{
op=read();
p[n+i].x=read()+1;
p[n+i].y=read()+1;
p[n+i].tm=n+i;
mxy=max(mxy,p[n+i].y);
if (op==2)
p[n+i].num=++ans[0],p[n+i].op=1;
}
for (int i=1;i<=ans[0];i++) ans[i]=0x3f3f3f3f;
mxy++;
for (int i=0;i<=mxy;i++) f[i]=0xc0c0c0c0;
sort(p+1,p+n+m+1);
solve(1,n+m);
for (int i=1;i<=ans[0];i++)
printf("%d\n",ans[i]);
return 0;
}

[bzoj] 2716 天使玩偶 || CDQ分治的更多相关文章

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

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

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

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

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

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

  4. bzoj 2716 天使玩偶(CDQ分治,BIT)

    [题目链接] http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=29234 [题意] 询问当前点与已知点的最小曼哈顿距离. [思路 ...

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

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

  6. BZOJ.2716.[Violet3]天使玩偶(CDQ分治 坐标变换)

    题目链接 考虑对于两个点a,b,距离为|x[a]-x[b]|+|y[a]-y[b]|,如果a在b的右上,那我们可以把绝对值去掉,即x[a]+y[a]-(x[b]+y[b]). 即我们要求满足x[b]& ...

  7. bzoj 2716 天使玩偶 —— K-D树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2716 果然和 bzoj 2648 是一样的吧: 只是数组要迷之开大,3e5+5 会RE? 代 ...

  8. 洛谷P4169 天使玩偶 CDQ分治

    还是照着CDQ的思路来. 但是有一些改动: 要求4个方向的,但是可爱的CDQ分治只能求在自己一个角落方向上的.怎么办?旋转!做4次就好了. 统计的不是和,而是——max!理由如下: 设当前点是(x,y ...

  9. CH 4701 - 天使玩偶 - [CDQ分治]

    题目链接:传送门 关于CDQ分治(参考李煜东<算法竞赛进阶指南>): 对于一系列操作,其中的任何一个询问操作,其结果必然等价于:初始值 + 此前所有的修改操作产生的影响. 假设共有 $m$ ...

随机推荐

  1. BZOJ1008: [HNOI2008]越狱(组合数)

    题目描述 监狱有连续编号为 1…N1…N 的 NN 个房间,每个房间关押一个犯人,有 MM 种宗教,每个犯人可能信仰其中一种.如果相邻房间的犯人的宗教相同,就可能发生越狱,求有多少种状态可能发生越狱. ...

  2. 【赛时总结】 ◇赛时·I◇ AtCoder ARC-098

    ◆赛时I◆ ARC-098 ■试题&解析■ ◆本场最水◆ C-Attention 长点儿信心吧-- [AtCoder ARC-098 C] [解析] 既然只存在左右(东西)两个朝向,那么领导右 ...

  3. bootloader 关闭看门狗

    #define pWTCON 0x53000000disable_watchdog: ldr r0, =pWTCON mov r1, #0x0 str r1, [r0]

  4. scrapy--Cookies

    大家好,之前看到的关于cookies的应用,由于有段时间没看,再看的时候花了一些时间,来给大家总结下.本文是根据:"http://www.bubuko.com/infodetail-2233 ...

  5. JS常用数组方法及实例

    1.join(separator):将数组的元素组起一个字符串,以separator为分隔符 ,,,,]; var b = a.join("|"); //如果不用分隔符,默认逗号隔 ...

  6. 时间轮算法的定时器(Delphi)

    源码下载 http://files.cnblogs.com/lwm8246/uTimeWheel.rar D7,XE2 编译测试OK //时间轮算法的定时器 //-- : QQ unit uTimeW ...

  7. hive 学习系列一(数据类型的定义)

    数字类型(Numeric Types) 整型 TINYINT(取值范围:-128 -- 127) SMALLINT(取值范围:-32,768 to 32,767) INT/INTEGER(取值范围: ...

  8. python——闰年的判断

    写一个程序,判断给定年份是否为闰年. 这样定义闰年的:能被4整除但不能被100整除,或者能被400整除都是闰年. while(1): year = input("请输入一个年份,让我判断一下 ...

  9. NC-瑞士军刀NetCat

    NC——Telnet/Banner 连接之后可以命令互动,比如POP3\SMTP\HTTP等协议命令 root@kali:/# nc -v pop3..com //-v详细显示 DNS fwd/rev ...

  10. 世界未解之谜之----------Android Gradle

    今天运行项目,运行的debug出来的包竟然是命名过的,但是我的buildTypes里面的debug 并没有执行重命名操作.很奇怪,我的猜测是: 执行buildTypes的时候,虽然是assermdeb ...