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

KD-tree可做,但是我不会暂时不考虑

大意:在二维平面内,给定n个点,m个操作。操作A:加入一个点;操作B:询问一个点与平面上加入的点的最近距离

不封装会T不封装会T不封装会T不封装会T不封装会T不封装会T不封装会T不封装会T不封装会T不封装会T不封装会T

把初始存在的点也看成加点操作

首先,曼哈顿距离取绝对值很烦,所以我们可以通过转坐标,把左上 右上 左下 右下通过转坐标都变成左下,最后取个min即可。于是对于(x,y)左下的点(x1,y1),dis=x-x1+y-y1=(x+y)-(x1+y1),用树状数组维护前缀最小值x1+y1。

按时间序排列,时间序 x y 三维偏序做CDQ分治即可

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 using namespace std;
  5 const int N=1000005,inf=1e9;
  6 int n,m,maxx,ans[N];
  7 struct BIT
  8 {
  9     int c[N];
 10     int lb(int x)
 11     {
 12         return x&(-x);
 13     }
 14     void update(int x,int d)
 15     {
 16         for(int i=x;i<=maxx;i+=lb(i))
 17             c[i]=max(c[i],d);
 18     }
 19     int ques(int x)
 20     {
 21         int ret=0;
 22         for(int i=x;i>=1;i-=lb(i))
 23             ret=max(ret,c[i]);
 24         return ret;
 25     }
 26     void clear(int x)
 27     {
 28         for(int i=x;i<=maxx;i+=lb(i))
 29             c[i] = 0;
 30     }
 31 }bit;
 32 struct qwe
 33 {
 34     int x,y,k,id;
 35     bool operator < (const qwe& rhs) const
 36     {
 37         if(x != rhs.x)
 38             return x < rhs.x;
 39         return id < rhs.id;
 40     }
 41 }a[N];
 42 struct CDQ
 43 {
 44     int n;
 45     qwe T[N];
 46     void init(int n)
 47     {
 48         this->n=n;
 49         sort(a+1,a+n+1);
 50     }
 51     void solve(int L, int R)
 52     {
 53         if(L>=R)
 54             return;
 55         int M=(L+R)>>1;
 56         int p=L,q=M+1;
 57         for(int i=L;i<=R;i++)
 58             if(a[i].id<=M)
 59                 T[p++]=a[i];
 60             else
 61                 T[q++]=a[i];
 62         for(int i=L;i<=R;i++)
 63             a[i]=T[i];
 64         solve(L,M);
 65         solve(M+1,R);
 66         int i=M+1,j=L;
 67         for(;i<=R;i++)
 68             if(a[i].k==2)
 69             {
 70                 for(;j<=M&&a[j].x<=a[i].x;j++)
 71                     if(a[j].k==1)
 72                         bit.update(a[j].y,a[j].x+a[j].y);
 73                 int t=bit.ques(a[i].y);
 74                 if(t)
 75                     ans[a[i].id]=min(ans[a[i].id],a[i].x+a[i].y-t);
 76             }
 77         for(int i=L;i<j;i++)
 78             if(a[i].k==1)
 79                 bit.clear(a[i].y);
 80         merge(a+L,a+M+1,a+M+1,a+R+1,T+L);
 81         for(int i=L;i<=R;i++)
 82             a[i]=T[i];
 83     }
 84 }cdq;
 85 int read()
 86 {
 87     int r=0;
 88     char p=getchar();
 89     while(p>‘9‘||p<‘0‘)
 90         p=getchar();
 91     while(p>=‘0‘&&p<=‘9‘)
 92     {
 93         r=r*10+p-48;
 94         p=getchar();
 95     }
 96     return r;
 97 }
 98 int main()
 99 {
100     n=read(),m=read();
101     for(int i=1;i<=n;i++)
102     {
103         a[i].x=read()+1;
104         a[i].y=read()+1;
105         a[i].id=i;
106         a[i].k=1;
107         maxx=max(maxx,max(a[i].x,a[i].y));
108     }
109     for(int i=n+1;i<=n+m;i++)
110     {
111         a[i].k=read();
112         a[i].x=read()+1;
113         a[i].y=read()+1;
114         a[i].id=i;
115         maxx=max(maxx,max(a[i].x,a[i].y));
116     }
117     maxx++;
118     n+=m;
119     for(int i=1;i<=n;i++)
120         ans[i]=inf;
121     cdq.init(n);
122     cdq.solve(1,n);
123     for(int i=1;i<=n;i++)
124         a[i].x=maxx-a[i].x;
125     cdq.init(n);
126     cdq.solve(1,n);
127     for(int i=1;i<=n;i++)
128         a[i].y=maxx-a[i].y;
129     cdq.init(n);
130     cdq.solve(1,n);
131     for(int i=1;i<=n;i++)
132         a[i].x=maxx-a[i].x;
133     cdq.init(n);
134     cdq.solve(1,n);
135     for(int i=1;i<=n;i++)
136         if(ans[i]!=inf)
137             printf("%d\n",ans[i]);
138     return 0;
139 }
时间: 2024-10-12 17:47:22

bzoj 2716 [Violet 3]天使玩偶 【CDQ分治】的相关文章

BZOJ 2716: [Violet 3]天使玩偶 [CDQ分治]

传送门 题意: 维护二维点集P,支持以下两个操作(1)插入点(x,y)(2)给定询问(x,y),求点集中离询问点最近的点距离定义为曼哈顿距离Dis(P1,P2)=|x1-x2|+|y1-y2|n,m<=500000x,y<=1000000 时间,$x$,$y$ $CDQ$分治里需要四个象限分类讨论,树状数组维护最大值 然后有两个象限是后缀和 然后跟$PoPoQQQ$学了一个神奇的技巧,树状数组加一个时间戳,就可以不用每次清空之前的操作了 #include <iostream> #i

BZOJ 2716: [Violet 3]天使玩偶

2716: [Violet 3]天使玩偶 Time Limit: 80 Sec  Memory Limit: 128 MBSubmit: 1473  Solved: 621[Submit][Status][Discuss] Description Input Output Sample Input & Output 样例过大,略 HINT Source Vani原创 欢迎移步 OJ2648 [Submit][Status][Discuss] CDQ分治,分类讨论拆绝对值的方式,分别查询最优值.

BZOJ 2648 SJY摆棋子 / 2716 Violet 3 天使玩偶 K-D树

题目大意:平面上有一些点,问一个点周围离它最近的点的曼哈顿距离是多少.支持动态加点. 思路:CDQ分治可以离线解决,但是SJY是卡CDQ的,天使玩偶可以过.毕竟K-D树的O(sqrt(n))的时间复杂度摆在那. K-D树理解起来其实不难,有k个维度的时候,每一层按照一个维度排序,取出按照这个维度排序的中位数,当作这个块的根,然后将这个块分开.还有一个比较重要的东西就是估价函数,这个函数根据不同的题可能不同.股价函数的主要用途就是对搜索进行剪枝,如果估价函数就已经大于当前的最优答案了,那就不用搜这

【BZOJ】2648: SJY摆棋子 &amp; 2716: [Violet 3]天使玩偶(kdtree)

http://www.lydsy.com/JudgeOnline/problem.php?id=2716 http://www.lydsy.com/JudgeOnline/problem.php?id=2648 双倍经验题... kdtree裸题吧.....今天学了下kdtree...感觉挺简单的.... 其实就是对几何图形进行剖分建树,而特殊在于,x和y轴轮流剖....这样可以提供很好的性质以便于查找... (一开始脑补了个treap代替kdtree.....显然我脑残了....写到一半发现这

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

Time Limit: 20 Sec  Memory Limit: 128 MB Description 这天,SJY显得无聊.在家自己玩.在一个棋盘上,有N个黑色棋子.他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找出距离这个白色棋子最近的黑色棋子.此处的距离是 曼哈顿距离 即(|x1-x2|+|y1-y2|) .现在给出N<=500000个初始棋子.和M<=500000个操作.对于每个白色棋子,输出距离这个白色棋子最近的黑色棋子的距离.同一个格子可能有多个棋子

【BZOJ 2716/2648】 [Violet 3]天使玩偶

2716: [Violet 3]天使玩偶 kd-tree模板题. ①首先依次按照每一维(即先按照x,再按照y,再按照x-多维同理)将点存在一棵二叉树中: 先求出以当前维数为关键字的中间点是谁(用到nth_element这个函数,可以直接把排名为k的放在第k位上,不保证其他有序:nth_element(a+1,a+1+k,a+1+n,cmp)) 为了一会儿查询中求估价函数方便,需要记录一下当前节点的子树中各维的极值(max,min) ②插入操作与splay的插入操作同理. ③询问操作的本质是搜索+

SJY摆棋子&amp;&amp;[Violet 3]天使玩偶

SJY摆棋子 https://www.lydsy.com/JudgeOnline/problem.php?id=2648 [Violet 3]天使玩偶 https://www.lydsy.com/JudgeOnline/problem.php?id=2716 参考博客:https://blog.csdn.net/Littlewhite520/article/details/78284697 KDtree模板题,带插入 1 #include<iostream> 2 #include<cst

【bzoj 2716】[Violet 3]天使玩偶 (CDQ+树状数组)

题目描述 Ayu 在七年前曾经收到过一个天使玩偶,当时她把它当作时间囊埋在了地下.而七年后 的今天,Ayu 却忘了她把天使玩偶埋在了哪里,所以她决定仅凭一点模糊的记忆来寻找它. 我们把 Ayu 生活的小镇看作一个二维平面坐标系,而 Ayu 会不定时地记起可能在某个点 (xmy) 埋下了天使玩偶:或者 Ayu 会询问你,假如她在 (x,y) ,那么她离近的天使玩偶可能埋下的地方有多远. 因为 Ayu 只会沿着平行坐标轴的方向来行动,所以在这个问题里我们定义两个点之间的距离为dist(A,B)=|A

BZOJ 2726: [SDOI2012]任务安排( dp + cdq分治 )

考虑每批任务对后面任务都有贡献, dp(i) = min( dp(j) + F(i) * (T(i) - T(j) + S) ) (i < j <= N)  F, T均为后缀和. 与j有关的量只有t = dp(j) - F(i) * T(j) , 我们要最小化它. dp(j)->y, T(j)->x, 那么y = F(i) * x + t, 就是给一些点和一个斜率...然后最小化截距, 显然维护下凸包就可以了. 然后因为无比坑爹的出题人....时间可以为负数, 所以要用平衡树维护(