BZOJ 1901. Zju2112 Dynamic Rankings
作者:互联网
整体二分和树套树都是 $O(n \log ^ 2 n)$ 的,但是整体二分的常数更小。
整体二分就是二分答案,然后就转化成区间数点问题,把区间里小于当前mid的数标成1,然后bit查询一下,再分成左右递归做下去。
#include <bits/stdc++.h> const int N = 5e4 + 7; const int INF = 1e9; struct Node { int x, y, k, pos, type; } q[N], q1[N], q2[N]; int n, m, a[N], ans[N], cnt, tol; struct Bit { int tree[N]; inline int lowbit(int x) { return x & -x; } inline void add(int x, int v) { for (int i = x; i <= n; i += lowbit(i)) tree[i] += v; } inline int query(int x) { int ans = 0; for (int i = x; i; i -= lowbit(i)) ans += tree[i]; return ans; } inline int query(int l, int r) { return query(r) - query(l - 1); } } bit; void solve(int l, int r, int L, int R) { if (l > r || L > R) return; if (l == r) { for (int i = L; i <= R; i++) if (q[i].type) ans[q[i].pos] = l; return; } int mid = l + r >> 1; int cnt1 = 0, cnt2 = 0; for (int i = L; i <= R; i++) { if (q[i].type) { int sum = bit.query(q[i].x, q[i].y); if (q[i].k > sum) q[i].k -= sum, q2[++cnt2] = q[i]; else q1[++cnt1] = q[i]; } else { if (q[i].x <= mid) bit.add(q[i].pos, q[i].y), q1[++cnt1] = q[i]; else q2[++cnt2] = q[i]; } } for (int i = 1; i <= cnt1; i++) if (!q1[i].type) bit.add(q1[i].pos, -q1[i].y); for (int i = 1; i <= cnt1; i++) q[L + i - 1] = q1[i]; for (int i = 1; i <= cnt2; i++) q[L + cnt1 + i - 1] = q2[i]; solve(l, mid, L, L + cnt1 - 1); solve(mid + 1, r, L + cnt1, R); } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) { scanf("%d", a + i); q[++cnt].x = a[i]; q[cnt].y = 1; q[cnt].pos = i; } for (int i = 1; i <= m; i++) { char s[3]; scanf("%s", s); if (s[0] == 'Q') { ++cnt; scanf("%d%d%d", &q[cnt].x, &q[cnt].y, &q[cnt].k); q[cnt].pos = ++tol; q[cnt].type = 1; } else { ++cnt; int x, y; scanf("%d%d", &x, &y); q[cnt].x = a[x]; q[cnt].y = -1; q[cnt].pos = x; ++cnt; q[cnt].x = a[x] = y; q[cnt].y = 1; q[cnt].pos = x; } } solve(-INF, INF, 1, cnt); for (int i = 1; i <= tol; i++) printf("%d\n", ans[i]); }View Code
树套树
#include <bits/stdc++.h> using namespace std; template<typename T> inline void read(T &x) { x = 0; T f = 1; char ch = getchar(); while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') { x = x * 10 + ch - 48; ch = getchar(); } x *= f; } const int N = 5e5 + 7; int n, m, ALL, x[N], y[N], totx, toty, v[N], a[N], root[N]; char s[3]; struct Q { bool opt; int l, r, k; } q[N]; inline int getid(int x) { return lower_bound(v + 1, v + ALL + 1, x) - v; } inline int lowbit(int x) { return x & -x; } struct Seg { struct Tree { int lp, rp, sum; } tree[N * 20]; int tol; void update(int &p, int q, int l, int r, int pos, int v) { tree[p = ++tol] = tree[q]; tree[p].sum += v; if (l == r) return; int mid = l + r >> 1; if (pos <= mid) update(tree[p].lp, tree[q].lp, l, mid, pos, v); else update(tree[p].rp, tree[q].rp, mid + 1, r, pos, v); } int query(int l, int r, int k) { if (l == r) return l; int sum = 0, mid = l + r >> 1; for (int i = 1; i <= totx; i++) sum -= tree[tree[x[i]].lp].sum; for (int i = 1; i <= toty; i++) sum += tree[tree[y[i]].lp].sum; if (k <= sum) { for (int i = 1; i <= totx; i++) x[i] = tree[x[i]].lp; for (int i = 1; i <= toty; i++) y[i] = tree[y[i]].lp; return query(l, mid, k); } else { for (int i = 1; i <= totx; i++) x[i] = tree[x[i]].rp; for (int i = 1; i <= toty; i++) y[i] = tree[y[i]].rp; return query(mid + 1, r, k - sum); } } } seg; void add(int x, int v) { int pos = getid(a[x]); for (int i = x; i <= n; i += lowbit(i)) seg.update(root[i], root[i], 1, ALL, pos, v); } int main() { read(n), read(m); for (int i = 1; i <= n; i++) read(a[i]), v[++ALL] = a[i]; for (int i = 1; i <= m; i++) { scanf("%s", s); if (s[0] == 'Q') { read(q[i].l), read(q[i].r), read(q[i].k); q[i].opt = 1; } else { q[i].opt = 0; read(q[i].l), read(q[i].r); v[++ALL] = q[i].r; } } sort(v + 1, v + ALL + 1); ALL = unique(v + 1, v + ALL + 1) - v - 1; for (int i = 1; i <= n; i++) add(i, 1); for (int i = 1; i <= m; i++) { if (q[i].opt) { totx = toty = 0; for (int j = q[i].l - 1; j; j -= lowbit(j)) x[++totx] = root[j]; for (int j = q[i].r; j; j -= lowbit(j)) y[++toty] = root[j]; printf("%d\n", v[seg.query(1, ALL, q[i].k)]); } else { add(q[i].l, -1); a[q[i].l] = q[i].r; add(q[i].l, 1); } } return 0; }View Code
标签:二分,ch,Zju2112,Rankings,int,cnt2,cnt1,inline,1901 来源: https://www.cnblogs.com/Mrzdtz220/p/12234062.html