其他分享
首页 > 其他分享> > BZOJ 1901. Zju2112 Dynamic Rankings

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