P3380 【模板】二逼平衡树(树套树)

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include<cstdlib>
#include<cmath>
#include<stack>
#include<map>
#include<string>
#include<vector>
#include<set>
#include<bitset>
#include<algorithm>
#include<ctime>
using namespace std;
#define ll long long
#define lb long double
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
#define ull unsigned long long
#define endl '\n'
#define clr(a, b) memset(a, b, sizeof(a))
#define lowbit(x) x & -x
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define PB push_back
#define POP pop_back
#define max_ll 9223372036854775807
#define PII pair<int, int>
#define random(x) (rand()%x)
//srand((ll)time(0));
//freopen("E://one.txt","r",stdin); //输入重定向,输入数据将从in.txt文件中读取
//freopen("E://oneout.txt","w",stdout); //输出重定向,输出数据将保存在out.txt文件中
//std::ios::sync_with_stdio(false);
const double eps = 1e-14;
const double pi = acos(-1);
const int maxn = 5e4 + 10;//30000000
const int maxm = maxn * 21;
const ll mod = 1e9 + 7;
const int hash_mod = 19260817;
const int inf = 2147483647;
int n, m, sz;
int tree[maxm], siz[maxm], val[maxm], ls[maxm], rs[maxm], a[maxn];
ll key[maxm];
inline int read(){
	char ch = getchar();
	int x = 0, f = 1;
	while(ch < '0' || ch > '9'){
		if(ch == '-') f = -1;
		ch = getchar();
	}
	while('0' <= ch && ch <= '9'){
		x = x * 10 + ch - '0';
		ch = getchar();
	}
	return x * f;
}
inline void write(int x){
	if (x < 0) x = ~x + 1, putchar('-');
	if (x > 9) write(x / 10);
	putchar(x % 10 + '0');
}
inline int add(int k){
    siz[++sz] = 1;
    val[sz] = k;
    key[sz] = rand();
    return sz;
}
inline void pushup(int rt){siz[rt] = siz[ls[rt]] + siz[rs[rt]] + 1;}
inline void split(int rt, int k, int & x, int & y){
    if(!rt){
        x = y = 0;
        return;
    }
    if(val[rt] <= k){
        x = rt;
        split(rs[rt], k, rs[rt], y);
    }
    else{
        y = rt;
        split(ls[rt], k, x, ls[rt]);
    }
    pushup(rt);
}
inline int hebin(int x, int y){
    if(!x || !y) return x + y;
    if(key[x] < key[y]){
        rs[x] = hebin(rs[x], y);
        pushup(x);
        return x;
    }
    else{
        ls[y] = hebin(x, ls[y]);
        pushup(y);
        return y;
    }
}
inline void Insert(int & rt, int k){
    int x, y;
    split(rt, k, x, y);
    rt = hebin(hebin(x, add(k)), y);
}
inline void Delete(int & rt, int k){
    int x, y, z;
    split(rt, k, x, z);
    split(x, k-1, x, y);
    y = hebin(ls[y], rs[y]);
    rt = hebin(hebin(x, y), z);
}
inline void build(int rt, int l, int r){
    for(int i = l ; i <= r ; ++ i) Insert(tree[rt], a[i]);
    if(l == r) return;
    int mid = (l + r) >> 1;
    build(lson); build(rson);
}
inline int Krank(int & rt, int k){
    int x, y;
    split(rt, k - 1, x, y);
    int rk = siz[x];
    rt = hebin(x, y);
    return rk;
}
inline int Kth(int rt, int k){
    while(1){
        if(k <= siz[ls[rt]]) rt = ls[rt];
        else if(k == siz[ls[rt]] + 1) return rt;
        else {k -= (siz[ls[rt]] + 1); rt = rs[rt];}
    }
}
inline int lst(int & rt, int k){
    int x, y, num;
    split(rt, k - 1, x, y);
    if(siz[x]) num = val[Kth(x, siz[x])];
    else num = -inf;
    rt = hebin(x, y);
    return num;
}
inline int nxt(int & rt, int k){
    int x, y, num;
    split(rt, k, x, y);
    if(siz[y]) num = val[Kth(y, 1)];
    else num = inf;
    rt = hebin(x, y);
    return num;
}
inline int q1(int rt, int l, int r, int L, int R, int k){
    if(L <= l && r <= R) return Krank(tree[rt], k);
    int mid = (l + r) >> 1;
    int ans = 0;
    if(L <= mid) ans += q1(lson, L, R, k);
    if(R > mid) ans += q1(rson, L, R, k);
    return ans;
}
inline void q3(int rt, int l, int r, int pos, int k){
    Delete(tree[rt], a[pos]);
    Insert(tree[rt], k);
    if(l == r) return;
    int mid = (l + r) >> 1;
    if(pos <= mid) q3(lson, pos, k);
    if(pos > mid) q3(rson, pos, k);
}
inline int q4(int rt, int l, int r, int L, int R, int k){
    if(L <= l && r <= R) return lst(tree[rt], k);
    int mid = (l + r) >> 1;
    int ans = -inf;
    if(L <= mid) ans = max(ans, q4(lson, L, R, k));
    if(R > mid) ans = max(ans, q4(rson, L, R, k));
    return ans;
}
inline int q5(int rt, int l, int r, int L, int R, int k){
    if(L <= l && r <= R) return nxt(tree[rt], k);
    int mid = (l + r) >> 1;
    int ans = inf;
    if(L <= mid) ans = min(ans, q5(lson, L, R, k));
    if(R > mid) ans = min(ans, q5(rson, L, R, k));
    return ans;
}
int main(){
    //freopen("E://123.in","r",stdin); //输入重定向,输入数据将从in.txt文件中读取
    //freopen("E://oneout.txt","w",stdout); //输出重定向,输出数据将保存在out.txt文件中
    int op, l, r, k, pos;
    srand((ll)time(0));
    n = read(); m = read();
    for(int i = 1 ; i <= n ; ++ i){
        a[i] = read();
    }
    build(1, 1, n);
    while(m --){
        op = read();
        if(op == 1){
            l = read(); r = read(); k = read();
            write( q1(1, 1, n, l, r, k) + 1 ); putchar('\n');
        }
        else if(op == 2){
            l = read(); r = read(); k = read();
            int L = 0, R = 1e8, ans;
            while(L <= R){
                int mid = (L + R) >> 1;
                if(q1(1, 1, n, l, r, mid) + 1 <= k) L = mid + 1, ans = mid;
                else R = mid - 1;
            }
            write(ans); putchar('\n');
        }
        else if(op == 3){
            pos = read(); k = read();
            q3(1, 1, n, pos, k);
            a[pos] = k;
        }
        else if(op == 4){
            l = read(); r = read(); k = read();
            write( q4(1, 1, n, l, r, k) ); putchar('\n');
        }
        else if(op == 5){
            l = read(); r = read(); k = read();
            write( q5(1, 1, n, l, r, k) ); putchar('\n');
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值