Bzoj 3196 二逼平衡树

树状数组套线段树(值域线段树)记得离散化

# include <bits/stdc++.h>
# define IL inline
# define RG register
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll;
const int _(2e5 + 10), __(5e6 + 10), INF(2147483647);

IL ll Read(){
    RG char c = getchar(); RG ll x = 0, z = 1;
    for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
    for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
    return x * z;
}

int n, m, qo[_], ql[_], qr[_], qk[_], len, o[_], a[_];
int sz[__], ls[__], rs[__], rt[__], tmp[2][20], cnt, t0, t1;

IL void Modify(RG int &x, RG int l, RG int r, RG int id, RG int v){
    if(!x) x = ++cnt; sz[x] += v;
    if(l == r) return;
    RG int mid = (l + r) >> 1;
    if(id <= mid) Modify(ls[x], l, mid, id, v);
    else Modify(rs[x], mid + 1, r, id, v);
}

IL void Add(RG int x, RG int v){  for(RG int i = x; i <= n; i += i & -i) Modify(rt[i], 1, len, a[x], v);  }

IL int Query(RG int x, RG int l, RG int r, RG int id){
    if(l == r) return sz[x];
    RG int mid = (l + r) >> 1;
    if(id <= mid) return Query(ls[x], l, mid, id);
    else return sz[ls[x]] + Query(rs[x], mid + 1, r, id);
}

IL int Rank(RG int l, RG int r, RG int k){
    if(l > r) return 0;
    RG int sum = 0;
    for(RG int i = r; i; i -= i & -i) sum += Query(rt[i], 1, len, k);
    for(RG int i = l - 1; i; i -= i & -i) sum -= Query(rt[i], 1, len, k);
    return sum;
}

IL int Find_Kth(RG int l, RG int r, RG int k){
    if(l == r) return l;
    RG int mid = (l + r) >> 1, sum = 0;
    for(RG int i = 1; i <= t1; ++i) sum += sz[ls[tmp[1][i]]];
    for(RG int i = 1; i <= t0; ++i) sum -= sz[ls[tmp[0][i]]];
    if(sum >= k){
        for(RG int i = 1; i <= t1; ++i) tmp[1][i] = ls[tmp[1][i]];
        for(RG int i = 1; i <= t0; ++i) tmp[0][i] = ls[tmp[0][i]];
        return Find_Kth(l, mid, k);
    }
    else{
        for(RG int i = 1; i <= t1; ++i) tmp[1][i] = rs[tmp[1][i]];
        for(RG int i = 1; i <= t0; ++i) tmp[0][i] = rs[tmp[0][i]];
        return Find_Kth(mid + 1, r, k - sum);
    }
}

IL int Kth(RG int l, RG int r, RG int k){
    t0 = t1 = 0;
    for(RG int i = l - 1; i; i -= i & -i) tmp[0][++t0] = rt[i];
    for(RG int i = r; i; i -= i & -i) tmp[1][++t1] = rt[i];
    return o[Find_Kth(1, len, k)];
}

int main(RG int argc, RG char* argv[]){
    n = Read(); m = Read();
    for(RG int i = 1; i <= n; ++i) a[i] = Read(), o[++len] = a[i];
    for(RG int i = 1; i <= m; ++i){
        qo[i] = Read();
        if(qo[i] == 3) ql[i] = qr[i] = Read(), qk[i] = Read();
        else ql[i] = Read(), qr[i] = Read(), qk[i] = Read();
        if(qo[i] != 2) o[++len] = qk[i];
    }
    sort(o + 1, o + len + 1); len = unique(o + 1, o + len + 1) - o - 1;
    for(RG int i = 1; i <= n; ++i) a[i] = lower_bound(o + 1, o + len + 1, a[i]) - o, Add(i, 1);
    for(RG int i = 1; i <= m; ++i){
        if(qo[i] == 3){
            Add(ql[i], -1);
            a[ql[i]] = lower_bound(o + 1, o + len + 1, qk[i]) - o;
            Add(ql[i], 1);
        }
        else if(qo[i] == 1){
            qk[i] = lower_bound(o + 1, o + len + 1, qk[i]) - o;
            printf("%d\n", Rank(ql[i], qr[i], qk[i] - 1) + 1);
        }
        else if(qo[i] == 2) printf("%d\n", Kth(ql[i], qr[i], qk[i]));
        else if(qo[i] == 4){
            qk[i] = lower_bound(o + 1, o + len + 1, qk[i]) - o;
            RG int sum = Rank(ql[i], qr[i], qk[i] - 1);
            printf("%d\n", Kth(ql[i], qr[i], sum));
        }
        else{
            qk[i] = lower_bound(o + 1, o + len + 1, qk[i]) - o;
            RG int sum = Rank(ql[i], qr[i], qk[i]);
            printf("%d\n", Kth(ql[i], qr[i], sum + 1));
        }
    }
    return 0;
}
posted @ 2018-01-05 17:27  Cyhlnj  阅读(167)  评论(0编辑  收藏  举报