BZOJ 2716: [Violet 3]天使玩偶

2716: [Violet 3]天使玩偶

Time Limit: 80 Sec  Memory Limit: 128 MB
Submit: 1473  Solved: 621
[Submit][Status][Discuss]

Description

Input

Output

Sample Input & Output

样例过大,略

HINT

Source

Vani原创 欢迎移步 OJ2648

[Submit][Status][Discuss]

CDQ分治,分类讨论拆绝对值的方式,分别查询最优值。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4
  5 inline int nextChar(void) {
  6     const int siz = 1024;
  7     static char buf[siz];
  8     static char *hd = buf + siz;
  9     static char *tl = buf + siz;
 10     if (hd == tl)
 11         fread(hd = buf, 1, siz, stdin);
 12     return int(*hd++);
 13 }
 14
 15 inline int nextInt(void) {
 16     register int ret = 0;
 17     register int neg = false;
 18     register int bit = nextChar();
 19     for (; bit < 48; bit = nextChar())
 20         if (bit == ‘-‘)neg ^= true;
 21     for (; bit > 47; bit = nextChar())
 22         ret = ret * 10 + bit - 48;
 23     return neg ? -ret : ret;
 24 }
 25
 26 const int lim = 1000001;
 27 const int siz = 1000005;
 28 const int inf = 1000000007;
 29
 30 int n, m;
 31
 32 struct data {
 33     int k, x, y, t, p;
 34     inline friend bool operator <
 35     (const data &a, const data &b) {
 36         if (a.x != b.x)
 37             return a.x < b.x;
 38         else
 39             return a.k < b.k;
 40     }
 41 }p[siz], s[siz], q[siz];
 42
 43 int ans[siz];
 44
 45 int now;
 46 int bit[siz];
 47 int tim[siz];
 48
 49 inline void add(int t, int k) {
 50     for (; t < siz; t += t&-t)
 51         if (bit[t] < k || tim[t] != now)
 52             bit[t] = k, tim[t] = now;
 53 }
 54
 55 inline int ask(int t) {
 56     int ret = -inf;
 57     for (; t; t -= t&-t)
 58         if (ret < bit[t] && tim[t] == now)
 59             ret = bit[t];
 60     return ret;
 61 }
 62
 63 void cdqSolve(int l, int r) {
 64     if (l >= r)return;
 65
 66     int mid = (l + r) >> 1;
 67
 68     cdqSolve(l, mid);
 69     cdqSolve(mid + 1, r);
 70
 71     int t1 = l, t2 = mid + 1, tot = l;
 72
 73     while (t1 <= mid && t2 <= r) {
 74         if (s[t1] < s[t2])
 75             q[tot++] = s[t1++];
 76         else
 77             q[tot++] = s[t2++];
 78     }
 79
 80     while (t1 <= mid)
 81         q[tot++] = s[t1++];
 82
 83     while (t2 <= r)
 84         q[tot++] = s[t2++];
 85
 86     for (int i = l; i <= r; ++i)
 87         s[i] = q[i];
 88
 89     ++now;
 90
 91     for (int i = l; i <= r; ++i)
 92         if (s[i].k && s[i].t > mid) {
 93             int tmp = s[i].x + s[i].y - ask(s[i].y);
 94             if (ans[s[i].p] > tmp)
 95                 ans[s[i].p] = tmp;
 96         }
 97         else if (!s[i].k && s[i].t <= mid)
 98             add(s[i].y, s[i].x + s[i].y);
 99 }
100
101 inline void cdqSolve1(void) {
102     memcpy(s, p, sizeof(s));
103     cdqSolve(1, n + m);
104 }
105
106 inline void cdqSolve2(void) {
107     memcpy(s, p, sizeof(s));
108     for (int i = 1; i <= n + m; ++i)
109         s[i].x = lim - s[i].x;
110     cdqSolve(1, n + m);
111 }
112
113 inline void cdqSolve3(void) {
114     memcpy(s, p, sizeof(s));
115     for (int i = 1; i <= n + m; ++i)
116         s[i].y = lim - s[i].y;
117     cdqSolve(1, n + m);
118 }
119
120 inline void cdqSolve4(void) {
121     memcpy(s, p, sizeof(s));
122     for (int i = 1; i <= n + m; ++i)
123         s[i].x = lim - s[i].x,
124         s[i].y = lim - s[i].y;
125     cdqSolve(1, n + m);
126 }
127
128 signed main(void) {
129 //    freopen("in", "r", stdin);
130 //    freopen("out", "w", stdout);
131
132     n = nextInt();
133     m = nextInt();
134
135     for (int i = 1; i <= n; ++i) {
136         p[i].x = nextInt();
137         p[i].y = nextInt();
138         p[i].k = 0;
139         p[i].t = i;
140     }
141
142     for (int i = 1; i <= m; ++i) {
143         p[i + n].k = nextInt() - 1;
144         p[i + n].x = nextInt();
145         p[i + n].y = nextInt();
146         p[i + n].t = i + n;
147         p[i + n].p = i;
148     }
149
150     for (int i = 1; i <= m; ++i)
151         ans[i] = inf;
152
153     cdqSolve1();
154     cdqSolve2();
155     cdqSolve3();
156     cdqSolve4();
157
158     for (int i = 1; i <= m; ++i)
159         if (p[i + n].k)printf("%d\n", ans[i]);
160 }

@Author: YouSiki

时间: 2025-01-13 15:24:47

BZOJ 2716: [Violet 3]天使玩偶的相关文章

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]天使玩偶 【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

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

BZOJ2716 &amp; NKOJ2739:[Violet 3]天使玩偶——题解

同样方便非权限玩家,NKOJ有这道题. http://oi.nks.edu.cn/zh/Problem/Details/2739 http://www.lydsy.com/JudgeOnline/problem.php?id=2716 样例输入 2 31 12 32 1 21 3 32 4 2 样例输出 1 2 ———————————————————————————————— 整整一个上午的时间,终于DEBUG出来了,原来是因为我数组开小了…… 首先我们很容易想到一个三元组(t,x,y),其中t