Luogu P4169 [Violet]天使玩偶/SJY摆棋子
学了不清真的\(sort\)写法\(CDQ\)分治的蒟蒻在本题的数据面前瑟瑟发抖。。。。。
实际上就是一个常规的\(CDQ\)模型,但是关键难点有两个:
-
需要进行四次\(CDQ\)。你可以选择把图旋转四次,
也可以像我一样写四次\(solve\)从而获得\(7kb\)的代码 -
用树状数组维护区间最大值的时候\(y\)可能为\(0\),会死循环,要\(+1\)处理。
-
不要使用不清真的\(sort\)写法!
\(Code:\)
// luogu-judger-enable-o2
#include <bits/stdc++.h>
using namespace std;
const int N = 300000 + 5;
const int M = 600000 + 5;
const int K = 1000000 + 100;
const int MaxK = 1000000 + 50;
const int INF = 0x3f3f3f3f;
#define lowbit(x) (x & -x)
int n, m, tot, qry[N], qryid;
struct Node {
int x, y, w, id, ans, opt; // 1 / 2 : 操作 / 查询
void out () {
if (opt == 1) {
cout << "{Opt : (" << x << ", " << y << "), w = " << w << "}";
} else {
cout << "{Qry : (" << x << ", " << y << "), w = " << w << " id = " << id << " ans = " << ans << "}";
}
}
}arr[M], tmp[M];
bool cmp1 (Node lhs, Node rhs) {return lhs.x == rhs.x ? lhs.y < rhs.y : lhs.x < rhs.x;} // x1 <= x2, y1 <= y2
bool cmp2 (Node lhs, Node rhs) {return lhs.x == rhs.x ? lhs.y > rhs.y : lhs.x < rhs.x;} // x1 <= x2, y1 >= y2
bool cmp3 (Node lhs, Node rhs) {return lhs.x == rhs.x ? lhs.y < rhs.y : lhs.x > rhs.x;} // x1 >= x2, y1 <= y2
bool cmp4 (Node lhs, Node rhs) {return lhs.x == rhs.x ? lhs.y > rhs.y : lhs.x > rhs.x;} // x1 >= x2, y1 >= y2
int tree[K];
void add_val (int pos, int val) {
while (pos < K) {
tree[pos] = max (tree[pos], val);
pos += lowbit (pos);
}
}
int get_val (int pos) {
int ret = -INF;
while (pos != 0) {
ret = max (ret, tree[pos]);
pos -= lowbit (pos);
}
return ret;
}
void clear (int pos) {
while (pos < K) {
tree[pos] = -INF;
pos += lowbit (pos);
}
}
Node _loc[M];
void cdq1 (int l, int r) {
if (r == l + 1) return;
int mid = (l + r) >> 1;
cdq1 (l, mid), cdq1 (mid, r);
// sort (tmp + l, tmp + mid, cmp1);
// sort (tmp + mid, tmp + r, cmp1);
int pl = l, pr = mid, k = l;
while (pr < r) {
while (pl < mid && tmp[pl].x <= tmp[pr].x) {
if (tmp[pl].opt == 1) {
add_val (tmp[pl].y + 1, tmp[pl].w);
}
_loc[k++] = tmp[pl++];
}
if (tmp[pr].opt == 2) {
tmp[pr].ans = min (tmp[pr].ans, tmp[pr].w - get_val (tmp[pr].y + 1) );
}
_loc[k++] = tmp[pr++];
}
for (int i = l; i < pl; ++i) {
clear (tmp[i].y + 1);
}
while (pl < mid) _loc[k++] = tmp[pl++];
for (int i = l; i < r; ++i) {
tmp[i] = _loc[i];
}
}
void solve1 () { // x1 <= x2, y1 <= y2
for (int i = 0; i < tot; i++) {
// 操作 : -(x1 + y1), 查询 (x2 + y2)
if (arr[i].opt == 1) {
tmp[i] = arr[i], tmp[i].w = + (arr[i].x + arr[i].y);
} else {
tmp[i] = arr[i], tmp[i].w = + (arr[i].x + arr[i].y);
}
}
cdq1 (0, tot);
for (int i = 0; i < tot; ++i) {
if (tmp[i].opt == 2) {
qry[tmp[i].id] = min (qry[tmp[i].id], tmp[i].ans);
}
}
}
void cdq2 (int l, int r) {
if (r == l + 1) return;
int mid = (l + r) >> 1;
cdq2 (l, mid), cdq2 (mid, r);
// sort (tmp + l, tmp + mid, cmp2);
// sort (tmp + mid, tmp + r, cmp2);
int pl = l, pr = mid, k = l;
while (pr < r) {
while (pl < mid && tmp[pl].x <= tmp[pr].x) {
if (tmp[pl].opt == 1) {
// cout << "Add : " << pl << endl;
add_val (MaxK - tmp[pl].y, tmp[pl].w);
}
_loc[k++] = tmp[pl++];
}
if (tmp[pr].opt == 2) {
// cout << "Qry : " << pr << endl;
tmp[pr].ans = min (tmp[pr].ans, tmp[pr].w - get_val (MaxK - tmp[pr].y));
}
_loc[k++] = tmp[pr++];
}
// cout << "l = " << l << " r = " << r << endl;
// cout << "Lside : " << endl;
// for (int i = l; i < mid; ++i) {
// tmp[i].out ();
// }
// cout << endl << endl;
// cout << "Rside : " << endl;
// for (int i = mid; i < r; ++i) {
// if (i != mid) cout << ", "; tmp[i].out ();
// }
// cout << endl << endl;
for (int i = l; i < pl; ++i) {
clear (MaxK - tmp[i].y);
}
while (pl < mid) _loc[k++] = tmp[pl++];
for (int i = l; i < r; ++i) {
tmp[i] = _loc[i];
}
}
void solve2 () { // x1 <= x2, y1 >= y2
for (int i = 0; i < tot; i++) {
if (arr[i].opt == 1) {
tmp[i] = arr[i], tmp[i].w = + (arr[i].x - arr[i].y);
} else {
tmp[i] = arr[i], tmp[i].w = + (arr[i].x - arr[i].y);
}
}
cdq2 (0, tot);
for (int i = 0; i < tot; ++i) {
if (tmp[i].opt == 2) {
qry[tmp[i].id] = min (qry[tmp[i].id], tmp[i].ans);
}
}
}
void cdq3 (int l, int r) {
if (r == l + 1) return;
int mid = (l + r) >> 1;
cdq3 (l, mid), cdq3 (mid, r);
// sort (tmp + l, tmp + mid, cmp3);
// sort (tmp + mid, tmp + r, cmp3);
int pl = l, pr = mid, k = l;
while (pr < r) {
while (pl < mid && tmp[pl].x >= tmp[pr].x) {
if (tmp[pl].opt == 1) {
add_val (tmp[pl].y + 1, tmp[pl].w);
}
_loc[k++] = tmp[pl++];
}
if (tmp[pr].opt == 2) {
tmp[pr].ans = min (tmp[pr].ans, tmp[pr].w - get_val (tmp[pr].y + 1) );
}
_loc[k++] = tmp[pr++];
}
for (int i = l; i < pl; ++i) {
clear (tmp[i].y + 1);
}
while (pl < mid) _loc[k++] = tmp[pl++];
for (int i = l; i < r; ++i) {
tmp[i] = _loc[i];
}
}
void solve3 () { // x1 <= x2, y1 >= y2
for (int i = 0; i < tot; i++) {
if (arr[i].opt == 1) {
tmp[i] = arr[i], tmp[i].w = + (arr[i].y - arr[i].x);
} else {
tmp[i] = arr[i], tmp[i].w = + (arr[i].y - arr[i].x);
}
}
cdq3 (0, tot);
for (int i = 0; i < tot; ++i) {
if (tmp[i].opt == 2) {
qry[tmp[i].id] = min (qry[tmp[i].id], tmp[i].ans);
}
}
}
void cdq4 (int l, int r) {
if (r == l + 1) return;
int mid = (l + r) >> 1;
cdq4 (l, mid), cdq4 (mid, r);
// sort (tmp + l, tmp + mid, cmp4);
// sort (tmp + mid, tmp + r, cmp4);
int pl = l, pr = mid, k = l;
while (pr < r) {
while (pl < mid && tmp[pl].x >= tmp[pr].x) {
if (tmp[pl].opt == 1) {
add_val (MaxK - tmp[pl].y, tmp[pl].w);
}
_loc[k++] = tmp[pl++];
}
if (tmp[pr].opt == 2) {
tmp[pr].ans = min (tmp[pr].ans, tmp[pr].w - get_val (MaxK - tmp[pr].y));
}
_loc[k++] = tmp[pr++];
}
for (int i = l; i < pl; ++i) {
clear (MaxK - tmp[i].y);
}
while (pl < mid) _loc[k++] = tmp[pl++];
for (int i = l; i < r; ++i) {
tmp[i] = _loc[i];
}
}
void solve4 () { // x1 <= x2, y1 >= y2
for (int i = 0; i < tot; i++) {
if (arr[i].opt == 1) {
tmp[i] = arr[i], tmp[i].w = - (arr[i].y + arr[i].x);
} else {
tmp[i] = arr[i], tmp[i].w = - (arr[i].y + arr[i].x);
}
}
cdq4 (0, tot);
for (int i = 0; i < tot; ++i) {
if (tmp[i].opt == 2) {
qry[tmp[i].id] = min (qry[tmp[i].id], tmp[i].ans);
}
}
}
int read () {
int s = 0, w = 1, ch = getchar ();
while ('9' < ch || ch < '0') {
if (ch == '-') w = -1;
ch = getchar ();
}
while ('0' <= ch && ch <= '9') {
s = s * 10 + ch - '0';
ch = getchar ();
}
return s * w;
}
int main () {
// freopen ("data.in", "r", stdin);
// freopen ("data.out", "w", stdout);
cin >> n >> m;
memset (tree, -0x3f, sizeof (tree));
for (int i = 0; i < n; ++i) {
static int x, y;
x = read (), y = read ();
arr[tot++] = (Node) {x, y, 0, 0, 0, 1};
}
for (int i = 0; i < m; ++i) {
static int opt, x, y;
opt = read (), x = read (), y = read ();
if (opt == 1) {
arr[tot++] = (Node) {x, y, 0, 0, 0, opt};
} else {
arr[tot++] = (Node) {x, y, 0, qryid++, INF, opt};
}
}
memset (qry, 0x3f, sizeof (qry));
solve1 (); solve2 ();
solve3 (); solve4 ();
for (int i = 0; i < qryid; ++i) {
printf ("%d\n", qry[i]);
}
}