ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

BZOJ 1901. Zju2112 Dynamic Rankings

2020-01-26 12:55:25  阅读:236  来源: 互联网

标签:二分 ch Zju2112 Rankings int cnt2 cnt1 inline 1901


 

整体二分和树套树都是 $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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有