• 洛谷P2617 Dynamic Rankings


    带修主席树模板题

    主席树的单点修改就是把前缀和(大概)的形式改成用树状数组维护,每个树状数组的元素都套了一个主席树(相当于每个数组的元素root[i]都是主席树,且这个主席树维护了(i - lowbit(i) + 1, i)这个区间的值域信息)

    修改的时候就是沿着lowbit把包含了该点的区间全部替换成新的线段树就行了~

    回答和静态主席树差不多,不过不是两颗树相减,因为要知道前缀所有值域的信息,所以区间左边和右边都要同时往后沿着lowbit跳完所有的主席树。

    注意的是主席树修改需要离线,因为我们要先离散化,如果提前处理好修改的值的话,离散化之后可能会没有新数的位置。

    #include <bits/stdc++.h>
    #define INF 0x3f3f3f3f
    #define full(a, b) memset(a, b, sizeof a)
    using namespace std;
    typedef long long ll;
    inline int lowbit(int x){ return x & (-x); }
    inline int read(){
        int X = 0, w = 0; char ch = 0;
        while(!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }
        while(isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();
        return w ? -X : X;
    }
    inline int gcd(int a, int b){ return a % b ? gcd(b, a % b) : b; }
    inline int lcm(int a, int b){ return a / gcd(a, b) * b; }
    template<typename T>
    inline T max(T x, T y, T z){ return max(max(x, y), z); }
    template<typename T>
    inline T min(T x, T y, T z){ return min(min(x, y), z); }
    template<typename A, typename B, typename C>
    inline A fpow(A x, B p, C lyd){
        A ans = 1;
        for(; p; p >>= 1, x = 1LL * x * x % lyd)if(p & 1)ans = 1LL * x * ans % lyd;
        return ans;
    }
    const int N = 300005;
    int n, m, cnt, tot, x, y, a[N], b[N], lc[N<<8], rc[N<<8], root[N], tree[N<<8], lt[N], rt[N];
    struct Query{
        bool isq;
        int l, r, pos, k;
    }query[100005];
    
    int modify(int rt, int l, int r, int pos, int k){
        int cur = ++cnt;
        tree[cur] = tree[rt] + k, lc[cur] = lc[rt], rc[cur] = rc[rt];
        if(l == r) return cur;
        int mid = (l + r) >> 1;
        if(pos <= mid) lc[cur] = modify(lc[rt], l, mid, pos, k);
        else rc[cur] = modify(rc[rt], mid + 1, r, pos, k);
        return cur;
    }
    
    void add(int k, int x){
        int p = (int)(lower_bound(b + 1, b + tot + 1, a[k]) - b);
        for(int i = k; i <= n; i += lowbit(i))
            root[i] = modify(root[i], 1, tot, p, x);
    }
    
    int queryQAQ(int k, int l, int r){
        if(l == r) return l;
        int suml = 0, sumr = 0;
        for(int i = 1; i <= x; i ++) suml += tree[lc[lt[i]]];
        for(int i = 1; i <= y; i ++) sumr += tree[lc[rt[i]]];
        int mid = (l + r) >> 1;
        if(sumr - suml >= k){
            for(int i = 1; i <= x; i ++) lt[i] = lc[lt[i]];
            for(int i = 1; i <= y; i ++) rt[i] = lc[rt[i]];
            return queryQAQ(k, l, mid);
        }
        else{
            for(int i = 1; i <= x; i ++) lt[i] = rc[lt[i]];
            for(int i = 1; i <= y; i ++) rt[i] = rc[rt[i]];
            return queryQAQ(k - (sumr - suml), mid + 1, r);
        }
    }
    
    int main(){
    
        n = read(), m = read();
        for(int i = 1; i <= n; i ++){
            a[i] = read();
            b[++tot] = a[i];
        }
        for(int i = 1; i <= m; i ++){
            char opt[3]; scanf("%s", opt);
            if(opt[0] == 'C'){
                query[i].isq = true;
                query[i].pos = read(), query[i].k = read();
                b[++tot] = query[i].k;
            }
            else{
                query[i].isq = false;
                query[i].l = read(), query[i].r = read(), query[i].k = read();
            }
        }
        sort(b + 1, b + tot + 1);
        tot = (int)(unique(b + 1, b + tot + 1) - b - 1);
        for(int i = 1; i <= n; i ++) add(i, 1);
        for(int i = 1; i <= m; i ++){
            if(query[i].isq){
                int pos = query[i].pos;
                add(pos, -1);
                a[pos] = query[i].k;
                add(pos, 1);
            }
            else{
                x = y = 0;
                for(int j = query[i].l - 1; j; j -= lowbit(j)) lt[++x] = root[j];
                for(int j = query[i].r; j; j -= lowbit(j)) rt[++y] = root[j];
                printf("%d
    ", b[queryQAQ(query[i].k, 1, tot)]);
            }
        }
        return 0;
    }
    

    贴个整体二分写法。。超级快。。

    #include <bits/stdc++.h>
    #define INF 0x3f3f3f3f
    #define full(a, b) memset(a, b, sizeof a)
    #define __fastIn ios::sync_with_stdio(false), cin.tie(0)
    #define pb push_back
    using namespace std;
    using LL = long long;
    inline int lowbit(int x){ return x & (-x); }
    inline int read(){
        int ret = 0, w = 0; char ch = 0;
        while(!isdigit(ch)){
            w |= ch == '-', ch = getchar();
        }
        while(isdigit(ch)){
            ret = (ret << 3) + (ret << 1) + (ch ^ 48);
            ch = getchar();
        }
        return w ? -ret : ret;
    }
    template <typename A>
    inline A __lcm(A a, A b){ return a / __gcd(a, b) * b; }
    template <typename A, typename B, typename C>
    inline A fpow(A x, B p, C lyd){
        A ans = 1;
        for(; p; p >>= 1, x = 1LL * x * x % lyd)if(p & 1)ans = 1LL * x * ans % lyd;
        return ans;
    }
    const int N = 200005;
    int n, m, cur, a[N], ans[N], c[N], cnt;
    char opt[5];
    struct Query{
        int op, id, x, y, k;
        Query(){}
        Query(int op, int x, int y, int k): op(op), x(x), y(y), k(k){
            id = 0;
        }
        Query(int op, int id, int x, int y, int k): op(op), id(id), x(x), y(y), k(k){}
    }v[N<<1], lq[N<<1], rq[N<<1];
    
    inline void add(int k, int val){
        for(; k <= n; k += lowbit(k)) c[k] += val;
    }
    
    inline int query(int k){
        int ret = 0;
        for(; k; k -= lowbit(k)) ret += c[k];
        return ret;
    }
    
    void solve(int L, int R, int l, int r){
        if(l > r) return;
        if(L == R){
            for(int i = l; i <= r; i ++){
                if(v[i].op) ans[v[i].id] = L;
            }
            return;
        }
        int mid = (L + R) >> 1;
        int lp = 0, rp = 0;
        for(int i = l; i <= r; i ++){
            if(!v[i].op){
                if(v[i].y <= mid) add(v[i].x, v[i].k), lq[++lp] = v[i];
                else rq[++rp] = v[i];
            }
            else{
                int ret = query(v[i].y) - query(v[i].x - 1);
                if(ret >= v[i].k) lq[++lp] = v[i];
                else v[i].k -= ret, rq[++rp] = v[i];
            }
        }
        for(int i = r; i >= l; i --){
            if(!v[i].op && v[i].y <= mid) add(v[i].x, -v[i].k);
        }
        for(int i = 1; i <= lp; i ++) v[l + i - 1] = lq[i];
        for(int i = 1; i <= rp; i ++) v[l + lp + i - 1] = rq[i];
        solve(L, mid, l, l + lp - 1);
        solve(mid + 1, R, l + lp, r);
    }
    
    int main(){
    
        n = read(), m = read();
        for(int i = 1; i <= n; i ++){
            a[i] = read();
            v[++cur] = Query(0, i, a[i], 1);
        }
        for(int i = 1; i <= m; i ++){
            scanf("%s", opt);
            if(opt[0] == 'Q'){
                int l = read(), r = read(), k = read();
                v[++cur] = Query(1, ++ cnt, l, r, k);
            }
            else{
                int x = read(), y = read();
                v[++cur] = Query(0, x, a[x], -1);
                a[x] = y;
                v[++cur] = Query(0, x, a[x], 1);
            }
        }
        solve(-INF, INF, 1, cur);
        for(int i = 1; i <= cnt; i ++){
            printf("%d
    ", ans[i]);
        }
        return 0;
    }
    
  • 相关阅读:
    Atitti 图像处理 图像混合 图像叠加 blend 原理与实现
    Atitit Gaussian Blur 高斯模糊 的原理and实现and 用途
    Atitit 图像处理 灰度图片 灰度化的原理与实现
    Atitit (Sketch Filter)素描滤镜的实现  图像处理  attilax总结
    Atitit 实现java的linq 以及与stream api的比较
    Atitit attilax在自然语言处理领域的成果
    Atitit 图像处理 常用8大滤镜效果 Jhlabs 图像处理类库 java常用图像处理类库
    Atitit 图像处理--图像分类 模式识别 肤色检测识别原理 与attilax的实践总结
    Atitit apache 和guava的反射工具
    atitit。企业的价值观 员工第一 vs 客户第一.docx
  • 原文地址:https://www.cnblogs.com/onionQAQ/p/10776556.html
Copyright © 2020-2023  润新知