zoukankan      html  css  js  c++  java
  • ZOJ

    题意:

      给出一个长度为N的序列。M次操作,Q代表询问区间的第K大值,C代表修改一个位置的数。输出每次询问的第K大值。

    题解:

      修改第i个位置的数会影响i~n。所以可以用树状数组维护每次修改。树状数组的每个节点代表一棵树,统计结果时对应位置相加即可。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 60010;
    int t;
    int n, m, num;
    int w[maxn];
    int tot;
    int root[maxn];
    char tt[2];
    vector<int> v;
    struct ask {
        int t, l, r, v;
    }q[10010];
    struct node {
        int l, r, sum;
    }tre[maxn*40];
    int use[maxn], tree[maxn];
    int getid(int x) {
        return lower_bound(v.begin(), v.end(), x)-v.begin()+1;
    }
    void update(int l, int r, int &x, int y, int pos, int val) {
        tre[++tot] = tre[y];
        tre[tot].sum += val;
        x = tot;
        if(l==r) return ;
        int mid = l+r>>1;
        if(pos<=mid) update(l, mid, tre[x].l, tre[y].l, pos, val);
        else update(mid+1, r, tre[x].r, tre[y].r, pos, val);
    }
    void add(int x, int pos, int val) {
        while(x <= n) {
            update(1, num, tree[x], tree[x], pos, val);
            x += x&(-x);
        }
    }
    int sum(int x) {
        int res = 0;
        while(x) {
            res += tre[tre[use[x]].l].sum;
            x -= x&(-x);
        }
        return res;
    }
    int query(int l, int r, int x, int y, int k, int ql, int qr) {
        if(l==r) return l;
        int mid = l+r>>1;
        int t = tre[tre[x].l].sum-tre[tre[y].l].sum+sum(qr)-sum(ql);
        if(t>=k) {
            for(int i = qr; i; i-=i&(-i)) 
            use[i] = tre[use[i]].l;
            for(int i = ql; i; i-=i&(-i)) 
            use[i] = tre[use[i]].l;
            return query(l, mid, tre[x].l, tre[y].l, k, ql, qr);
        }
        else {
            for(int i = qr; i > 0; i-=i&(-i)) 
            use[i] = tre[use[i]].r;
            for(int i = ql; i > 0; i-=i&(-i)) 
            use[i] = tre[use[i]].r;
            return query(mid+1, r, tre[x].r, tre[y].r, k-t, ql, qr);
        }
    }
    int main() {
        scanf("%d", &t);
        while(t--) {
            tot = 0;
            v.clear();
            memset(tree, 0, sizeof(tree));
            scanf("%d%d", &n, &m);
            for(int i = 1; i <= n; i++) {
                scanf("%d", &w[i]);
                v.push_back(w[i]);
            }
            for(int i = 1; i <= m; i++) {
                scanf("%s%d%d", tt, &q[i].l, &q[i].r);
                if(tt[0]=='C') q[i].t = 0, v.push_back(q[i].r);
                else scanf("%d", &q[i].v), q[i].t = 1;
            }
            sort(v.begin(), v.end());
            v.erase(unique(v.begin(), v.end()), v.end());
            num = v.size();
            for(int i = 1; i <= n; i++) update(1, num, root[i], root[i-1], getid(w[i]), 1);
            for(int i = 1; i <= m; i++) {
                if(q[i].t) {
                    for(int j = q[i].r; j; j-=j&(-j)) 
                    use[j] = tree[j];
                    for(int j = q[i].l-1; j; j-=j&(-j))
                    use[j] = tree[j];
                    printf("%d
    ", v[query(1, num, root[q[i].r], root[q[i].l-1], q[i].v, q[i].l-1, q[i].r)-1]);
                }
                else {
                    add(q[i].l, getid(w[q[i].l]), -1);
                    add(q[i].l, getid(q[i].r), 1);
                    w[q[i].l] = q[i].r; 
                }
            }
        }
    }
    View Code
  • 相关阅读:
    文件编码转换
    mysql密码的奇怪问题
    python文件读写
    python中JSON的使用
    mysql默认字符编码的修改
    烧写uboot与linux操作系统,安装Samba,jlink驱动安装
    Busybox是什么?
    ubuntu 搭建GTK+以及glade2集成开发环境的一些方法
    Ubuntu linux安装ssh server
    UBoot启动过程(国嵌)
  • 原文地址:https://www.cnblogs.com/Pneuis/p/8973487.html
Copyright © 2011-2022 走看看