2022 CCPC 华为云计算挑战赛 机器人
其实是补2023CCPC秦皇岛热身赛C
主要思路跟IOI2021分糖果是一样的,区别就是这里不是对总的区间二分,而是指定区间
所以先做一次区间询问把对应的log个线段树区间拿出来,然后就是二分一样的思路,不过是在序列上,所以要先逆序找到第一个不满足条件的线段树区间,然后进到它对应的子树里二分即可
常数巨大
#include <iostream> #include <algorithm> #include <vector> #define ls (x << 1) #define rs (x << 1 | 1) using namespace std; typedef long long LL; const int MAX_N = 5e5 + 5, MIN_V = -2e9, MAX_V = 2e9; int opt[2][MAX_N], sig[2][MAX_N]; vector<tuple<int,int,int>> q[2]; struct NODE{ LL lzy; int maxv, minv; NODE(LL cl = 0, int cx = 0, int cn = 0) : lzy{cl}, maxv{cx}, minv{cn} {} }; struct SGT{ NODE t[MAX_N << 2]; void pushup(int x) { t[x].maxv = max(t[ls].maxv, t[rs].maxv); t[x].minv = min(t[ls].minv, t[rs].minv); } void Merge(NODE &x, NODE l, NODE r) { x.maxv = max(l.maxv, r.maxv); x.minv = min(l.minv, r.minv); } void pushdown(int x) { LL v = t[x].lzy; t[x].lzy = 0; t[ls].lzy += v; t[ls].minv += v; t[ls].maxv += v; t[rs].lzy += v; t[rs].minv += v; t[rs].maxv += v; } void update(int L, int R, int l, int r, int x, int v) { if (L <= l && r <= R) { t[x].lzy += v; t[x].minv += v; t[x].maxv += v; return; } pushdown(x); int mid = l + r >> 1; if (L <= mid) update(L, R, l, mid, ls, v); if (mid < R) update(L, R, mid + 1, r, rs, v); pushup(x); } int getval(int D, int l, int r, int x) { if (l == r) return t[x].minv; pushdown(x); int mid = l + r >> 1; if (D <= mid) return getval(D, l, mid, ls); else return getval(D, mid + 1, r, rs); } void ask(int L, int R, int l, int r, int x, int op) { if (L <= l && r <= R) { q[op].push_back({x, l, r}); return; } pushdown(x); int mid = l + r >> 1; if (L <= mid) ask(L, R, l, mid, ls, op); if (mid < R) ask(L, R, mid + 1, r, rs, op); } int getans(int l, int r, int n, int m, int op) { NODE suf(0, MIN_V, MAX_V), nxt(0, MIN_V, MAX_V); int x = 0, lef = 0, rig = 0; for (int i = q[op].size() - 1; i >= 0; --i) { tie(x, lef, rig) = q[op][i]; Merge(nxt, t[x], suf); if (nxt.maxv - nxt.minv > n) { return getval(r, 0, m, 1) + query(lef, rig, x, n, suf); } suf = nxt; } return getval(r, 0, m, 1) - suf.minv; } int query(int l, int r, int x, int top, NODE suf) { if (l == r) { NODE cur = NODE(0, MIN_V, MAX_V); Merge(cur, t[x], suf); if (cur.minv == t[x].minv) return top - cur.maxv; else return -cur.minv; } pushdown(x); int mid = l + r >> 1; NODE nxt = NODE(0, MIN_V, MAX_V); Merge(nxt, t[rs], suf); if (nxt.maxv - nxt.minv > top) return query(mid + 1, r, rs, top, suf); else return query(l, mid, ls, top, nxt); } void build(int l, int r, int x, int op) { t[x].lzy = t[x].maxv = t[x].minv = 0; if (l == r) { t[x].maxv = t[x].minv = sig[op][l]; return; } int mid = l + r >> 1; build(l, mid, ls, op); build(mid + 1, r, rs, op); pushup(x); } }t[2]; char s[MAX_N]; int stk[30]; int rd() { int x= 0, c = getchar(); while (!isdigit(c)) c = getchar(); while (isdigit(c)) { x = (x << 1) + (x << 3) + (c ^ 48); c = getchar(); } return x; } void rds() { int c = getchar(), ptr = 0; while (!isupper(c)) c = getchar(); while (isupper(c)) { s[++ptr] = c; c = getchar(); } } void output(int x) { int top = 0; do { stk[top++] = x % 10; x /= 10; } while (x); while (top) { putchar('0' + stk[--top]); } } char rdc() { int c = getchar(); while (!isupper(c)) c = getchar(); return c; } void solve() { int n, m, k; n = rd(); m = rd(); k = rd(); rds(); for (int i = 1; i <= m; ++i) { opt[0][i] = opt[1][i] = 0; if (s[i] == 'U' || s[i] == 'D') { opt[0][i] = (s[i] == 'U' ? -1 : 1); } if (s[i] == 'L' || s[i] == 'R') { opt[1][i] = (s[i] == 'L' ? -1 : 1); } sig[0][i] = sig[0][i - 1] + opt[0][i]; sig[1][i] = sig[1][i - 1] + opt[1][i]; } t[0].build(0, m, 1, 0); t[1].build(0, m, 1, 1); int op, x[2], l, r, pos; char c; while (k--) { op = rd(); if (op == 1) { x[0] = rd() - 1; x[1] = rd() - 1; l = rd(); r = rd(); for (int i = 0; i < 2; ++i) { if (x[i]) t[i].update(l, r, 0, m, 1, x[i]); q[i].clear(); t[i].ask(l - 1, r, 0, m, 1, i); output(t[i].getans(l - 1, r, n - 1, m, i) + 1); if (i == 0) putchar(' '); if (x[i]) t[i].update(l, r, 0, m, 1, -x[i]); } putchar('\n'); } else { pos = rd(); c = rdc(); int cur = (s[pos] == 'U' || s[pos] == 'D') ? 0 : 1; if (opt[cur][pos]) t[cur].update(pos, m, 0, m, 1, -opt[cur][pos]); opt[cur][pos] = 0; if (c == 'U' || c == 'D') { opt[0][pos] = (c == 'U' ? -1 : 1); t[0].update(pos, m, 0, m, 1, opt[0][pos]); } else { opt[1][pos] = (c == 'L' ? -1 : 1); t[1].update(pos, m, 0, m, 1, opt[1][pos]); } s[pos] = c; } } } int main() { int T = 1; T = rd(); while (T--) { solve(); } return 0; }
禁止诸如开发者知识库/布布扣/码迷/学步园/马开东等 copy 他人博文乃至博客的网站转载
,用户转载请注明出处:https://www.cnblogs.com/xcysblog/