2022 CCPC 华为云计算挑战赛 机器人

发布时间 2023-11-01 14:57:46作者: EvalonXing

题目链接

其实是补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;
}