luogu 3380

树状数组套权值线段树

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>

#define E exit(0)

using namespace std;

#define LL long long

#define gc getchar()
inline int read() {int x = 0; char c = gc; while(c < '0' || c > '9') c = gc;
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc; return x;}
inline LL read_LL() {LL x = 0; char c = gc; while(c < '0' || c > '9') c = gc;
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc; return x;}
#undef gc

const int N = 5e4 + 10;
const int Out = 2147483647;

struct Node {int opt, l, r, k;} Ask[N];
int n, m;
int Num[N << 1], totNum, A[N], Length;

int Root[N];
int W[N * 125], Lson[N * 125], Rson[N * 125];

int Add_root[N], Cut_root[N];
int Hjt_;

namespace Seg {
    
    void Insert(int &rt, int l, int r, int x) {
        if(!rt) rt = ++ Hjt_;
        W[rt] ++;
        if(l == r) return ;
        int mid = (l + r) >> 1;
        if(x <= mid) Insert(Lson[rt], l, mid, x);
        else Insert(Rson[rt], mid + 1, r, x);
    }
    
    int Getrank(int l, int r, int k, int opt) {
        if(l == r) {
            if(opt == 0) return 1;
            int s = 0;
            for(int i = 1; i <= Add_root[0]; i ++) s += W[Add_root[i]];
            for(int i = 1; i <= Cut_root[0]; i ++) s -= W[Cut_root[i]];
            return s;
        }
        int mid = (l + r) >> 1;
        if(k <= mid) {
            for(int i = 1; i <= Add_root[0]; i ++) Add_root[i] = Lson[Add_root[i]];
            for(int i = 1; i <= Cut_root[0]; i ++) Cut_root[i] = Lson[Cut_root[i]];
            return Getrank(l, mid, k, opt);
        } else {
            int sum = 0;
            for(int i = 1; i <= Add_root[0]; i ++) {
                sum += W[Lson[Add_root[i]]]; Add_root[i] = Rson[Add_root[i]];    
            }
            for(int i = 1; i <= Cut_root[0]; i ++) {
                sum -= W[Lson[Cut_root[i]]]; Cut_root[i] = Rson[Cut_root[i]];    
            }
            int ret = sum + Getrank(mid + 1, r, k, opt);
            return ret;
        }
    }
    
    int Getnum(int l, int r, int k) {
        if(l == r) return l;
        int mid = (l + r) >> 1;
        int sum = 0;
        for(int i = 1; i <= Add_root[0]; i ++) sum += W[Lson[Add_root[i]]];
        for(int i = 1; i <= Cut_root[0]; i ++) sum -= W[Lson[Cut_root[i]]];
        if(sum >= k) {
            for(int i = 1; i <= Add_root[0]; i ++) Add_root[i] = Lson[Add_root[i]];
            for(int i = 1; i <= Cut_root[0]; i ++) Cut_root[i] = Lson[Cut_root[i]];
            Getnum(l, mid, k);
        } else {
            for(int i = 1; i <= Add_root[0]; i ++) Add_root[i] = Rson[Add_root[i]];
            for(int i = 1; i <= Cut_root[0]; i ++) Cut_root[i] = Rson[Cut_root[i]];
            Getnum(mid + 1, r, k - sum);
        }
    }
    
    void Poi_G(int l, int r, int x, int val) {
        for(int i = 1; i <= Cut_root[0]; i ++) W[Cut_root[i]] += val;
        if(l == r) return ;
        int mid = (l + r) >> 1;
        if(x <= mid) {
            for(int i = 1; i <= Cut_root[0]; i ++) {
                if(Lson[Cut_root[i]] == 0) Lson[Cut_root[i]] = ++ Hjt_;
                Cut_root[i] = Lson[Cut_root[i]];
            }
            Poi_G(l, mid, x, val);
        } else {
            for(int i = 1; i <= Cut_root[0]; i ++) {
                if(Rson[Cut_root[i]] == 0) Rson[Cut_root[i]] = ++ Hjt_;
                Cut_root[i] = Rson[Cut_root[i]];
            }
            Poi_G(mid + 1, r, x, val);
        }
    }
    
    int Asknum(int l, int r, int k) {
        if(l == r) {
            int sum = 0;
            for(int i = 1; i <= Add_root[0]; i ++) sum += W[Add_root[i]];
            for(int i = 1; i <= Cut_root[0]; i ++) sum -= W[Cut_root[i]];
            k -= sum;
            if(k > 0) return -1;
            return l;
        }
        int sum = 0;
        for(int i = 1; i <= Add_root[0]; i ++) sum += W[Lson[Add_root[i]]];
        for(int i = 1; i <= Cut_root[0]; i ++) sum -= W[Lson[Cut_root[i]]];
        int mid = (l + r) >> 1;
        if(k <= sum) {
            for(int i = 1; i <= Add_root[0]; i ++) Add_root[i] = Lson[Add_root[i]];
            for(int i = 1; i <= Cut_root[0]; i ++) Cut_root[i] = Lson[Cut_root[i]];
            Asknum(l, mid, k);
        } else {
            for(int i = 1; i <= Add_root[0]; i ++) Add_root[i] = Rson[Add_root[i]];
            for(int i = 1; i <= Cut_root[0]; i ++) Cut_root[i] = Rson[Cut_root[i]];
            Asknum(mid + 1, r, k - sum);
        }
    }
}

namespace Bit {
    
    inline int Lowbit(int x) {return (x & (-x));}
    
    void Add(int rt, int x, int val) {
        for(int i = rt; i <= n; i += Lowbit(i)) {
            Seg:: Insert(Root[i], 1, Length, x);
        }
    }
    
    int Getrank(int l, int r, int k) {
        Add_root[0] = Cut_root[0] = 0;
        for(int i = r; i >= 1; i -= Lowbit(i)) Add_root[++ Add_root[0]] = Root[i];
        for(int i = l - 1; i >= 1; i -= Lowbit(i)) Cut_root[++ Cut_root[0]] = Root[i];
        k = lower_bound(Num + 1, Num + Length + 1, k) - Num;
        return Seg:: Getrank(1, Length, k, 0);
     }
    
    int Getnum(int l, int r, int k) {
        Add_root[0] = Cut_root[0] = 0;
        for(int i = r; i >= 1; i -= Lowbit(i)) {
            Add_root[++ Add_root[0]] = Root[i];
        }
        for(int i = l - 1; i >= 1; i -= Lowbit(i)) {
            Cut_root[++ Cut_root[0]] = Root[i];    
        }
        return Seg:: Getnum(1, Length, k);
    }
    
    void Poi_G(int x, int k) {
        Cut_root[0] = 0;
        for(int i = x; i <= n; i += Lowbit(i)) Cut_root[++ Cut_root[0]] = Root[i];
        int a = lower_bound(Num + 1, Num + Length + 1, A[x]) - Num;
        A[x] = k;
        Seg:: Poi_G(1, Length, a, -1);
        Cut_root[0] = 0;
        for(int i = x; i <= n; i += Lowbit(i)) Cut_root[++ Cut_root[0]] = Root[i];
        a = lower_bound(Num + 1, Num + Length + 1, k) - Num;
        Seg:: Poi_G(1, Length, a, 1);
    }
    
    int Asknum(int l, int r, int k, int opt) {
        k = lower_bound(Num + 1, Num + Length + 1, k) - Num;
        int kk = k;
        Add_root[0] = Cut_root[0] = 0;
        for(int i = r; i >= 1; i -= Lowbit(i)) Add_root[++ Add_root[0]] = Root[i];
        for(int i = l - 1; i >= 1; i -= Lowbit(i)) Cut_root[++ Cut_root[0]] = Root[i];
        k = Seg:: Getrank(1, Length, k, 0);
        Add_root[0] = Cut_root[0] = 0;
        for(int i = r; i >= 1; i -= Lowbit(i)) Add_root[++ Add_root[0]] = Root[i];
        for(int i = l - 1; i >= 1; i -= Lowbit(i)) Cut_root[++ Cut_root[0]] = Root[i];
        int k2 = Seg:: Getrank(1, Length, kk, 1);
        Add_root[0] = Cut_root[0] = 0;
        for(int i = r; i >= 1; i -= Lowbit(i)) Add_root[++ Add_root[0]] = Root[i];
        for(int i = l - 1; i >= 1; i -= Lowbit(i)) Cut_root[++ Cut_root[0]] = Root[i];
        if(opt == 1) {
            if(k == 1) return -1;
            return Seg:: Asknum(1, Length, k - 1);    
        }
        else return Seg:: Asknum(1, Length, k2 + 1);
    }
}

int main() {
    n = read(), m = read();
    for(int i = 1; i <= n; i ++) Num[i] = read(), A[i] = Num[i];
    totNum = n;
    for(int i = 1; i <= m; i ++) {
        Ask[i].opt = read();
        if(Ask[i].opt != 3) {Ask[i].l = read(), Ask[i].r = read(), Ask[i].k = read();}
        else Ask[i].l = read(), Ask[i].k = read(), Num[++ totNum] = Ask[i].k;
        if(Ask[i].opt == 4 || Ask[i].opt == 5) {
            Num[++ totNum] = Ask[i].k;
        }
    }
    sort(Num + 1, Num + totNum + 1);
    Length = unique(Num + 1, Num + totNum + 1) - Num - 1;
    for(int i = 1; i <= n; i ++) {
        int a = lower_bound(Num + 1, Num + Length + 1, A[i]) - Num;
        Bit:: Add(i, a, 1);
    }
    
    #define opt Ask[i].opt
    #define l Ask[i].l
    #define r Ask[i].r
    #define k Ask[i].k
    
    for(int i = 1; i <= m; i ++) {
        if(opt == 1) {
            cout << Bit:: Getrank(l, r, k) << "\n";
        } else if(opt == 2) {
            int ans = Bit:: Getnum(l, r, k);
            cout << Num[ans] << "\n";
        } else if(opt == 3) {
            Bit:: Poi_G(l, k);
        } else if(opt == 4) {
            int ans = Bit:: Asknum(l, r, k, 1);
            if(ans == -1) cout << "-2147483647" << "\n";
            else cout << Num[ans] << "\n";
        } else {
            int ans = Bit:: Asknum(l, r, k, 0);
            if(ans == -1) cout << "2147483647" << "\n";
            else cout << Num[ans] << "\n";
        }
    }
    return 0;
}

 

posted @ 2018-09-06 20:17  xayata  阅读(141)  评论(0编辑  收藏  举报