学了不清真的\(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]); } }
来源:https://www.cnblogs.com/maomao9173/p/10904083.html