【题目链接】
【思路要点】
- 用线段树模拟整数的加减,通过维护区间信息和区间赋值来实现快速进/退位。
- 具体而言,在每个节点维护该区间是否全为0/1,以及区间赋值懒标记。
- 进行加/减法时现在对应位上进行操作,若涉及进/退位,则在线段树上二分出最近的更高位的0/1,对其进行操作,并将操作位置和该位置之间的区间赋值为1/0。
- 进行压位,进制变为\(2^{30}\)。时间复杂度\(O(NLogN)\)。
【代码】
#include<bits/stdc++.h> using namespace std; const int MAXN = 1500005; const int MAXP = 2500005; const int s = (1 << 30) - 1; template <typename T> void chkmax(T &x, T y) {x = max(x, y); } template <typename T> void chkmin(T &x, T y) {x = min(x, y); } template <typename T> void read(T &x) { x = 0; int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; x *= f; } template <typename T> void write(T x) { if (x < 0) x = -x, putchar('-'); if (x > 9) write(x / 10); putchar(x % 10 + '0'); } template <typename T> void writeln(T x) { write(x); puts(""); } struct SegmentTree { struct Node { int lc, rc; bool tag, tagtype; bool all, alltype; } a[MAXP]; int root, size, n, val[MAXN]; void pushdown(int root, int l, int r) { if (!a[root].tag) return; if (l == r) { if (a[root].tagtype) val[l] = s; else val[l] = 0; } else { int tmp = a[root].lc; a[tmp].tag = true; a[tmp].tagtype = a[root].tagtype; a[tmp].all = true; a[tmp].alltype = a[root].tagtype; tmp = a[root].rc; a[tmp].tag = true; a[tmp].tagtype = a[root].tagtype; a[tmp].all = true; a[tmp].alltype = a[root].tagtype; } a[root].tag = false; } void update(int root, int l, int r) { if (l == r) { if (val[l] == s) { a[root].all = true; a[root].alltype = true; } else if (val[l] == 0) { a[root].all = true; a[root].alltype = false; } else a[root].all = false; } else { if (a[a[root].lc].all && a[a[root].rc].all && a[a[root].lc].alltype == a[a[root].rc].alltype) { a[root].all = true; a[root].alltype = a[a[root].lc].alltype; } else a[root].all = false; } } void build(int &root, int l, int r) { root = ++size; if (l == r) { update(root, l, r); return; } int mid = (l + r) / 2; build(a[root].lc, l, mid); build(a[root].rc, mid + 1, r); update(root, l, r); } void init(int x) { n = x; build(root, 0, n); } void access(int root, int l, int r, int pos) { pushdown(root, l, r); if (l == r) { update(root, l, r); return; } int mid = (l + r) / 2; if (mid >= pos) access(a[root].lc, l, mid, pos); else access(a[root].rc, mid + 1, r, pos); update(root, l, r); } int query(int pos, int bit) { access(root, 0, n, pos); return (val[pos] & (1 << bit)) != 0; } bool add(int root, int l, int r, int pos) { pushdown(root, l, r); int mid = (l + r) / 2; if (l > pos) { if (a[root].all && a[root].alltype) { a[root].alltype = false; a[root].tag = true; a[root].tagtype = false; return false; } if (l == r) { val[l]++; update(root, l, r); return true; } if (add(a[root].lc, l, mid, pos)) { update(root, l, r); return true; } bool ans = add(a[root].rc, mid + 1, r, pos); update(root, l, r); return ans; } if (mid > pos && add(a[root].lc, l, mid, pos)) { update(root, l, r); return true; } bool ans = add(a[root].rc, mid + 1, r, pos); update(root, l, r); return ans; } void add(int pos, int d) { access(root, 0, n, pos); val[pos] += d; if (val[pos] <= s) { access(root, 0, n, pos); return; } val[pos] &= s; access(root, 0, n, pos); add(root, 0, n, pos); } bool dec(int root, int l, int r, int pos) { pushdown(root, l, r); int mid = (l + r) / 2; if (l > pos) { if (a[root].all && !a[root].alltype) { a[root].alltype = true; a[root].tag = true; a[root].tagtype = true; return false; } if (l == r) { val[l]--; update(root, l, r); return true; } if (dec(a[root].lc, l, mid, pos)) { update(root, l, r); return true; } bool ans = dec(a[root].rc, mid + 1, r, pos); update(root, l, r); return ans; } if (mid > pos && dec(a[root].lc, l, mid, pos)) { update(root, l, r); return true; } bool ans = dec(a[root].rc, mid + 1, r, pos); update(root, l, r); return ans; } void dec(int pos, int d) { access(root, 0, n, pos); val[pos] -= d; if (val[pos] >= 0) { access(root, 0, n, pos); return; } val[pos] += 1 << 30; access(root, 0, n, pos); dec(root, 0, n, pos); } } ST; int n, t1, t2, t3; int main() { read(n), read(t1), read(t2), read(t3); ST.init(n + 1840); for (int i = 1; i <= n; i++) { int opt; read(opt); if (opt == 1) { long long x; int y; read(x), read(y); int pos = y / 30, bit = y % 30; if (x >= 0) { x <<= bit; ST.add(pos, x & s); ST.add(pos + 1, x >> 30); } else { x = -x; x <<= bit; ST.dec(pos, x & s); ST.dec(pos + 1, x >> 30); } } else { int x; read(x); writeln(ST.query(x / 30, x % 30)); } } return 0; }