树套树 - AcWing 2488

树套树 - AcWing 2488

树套树是一个非常暴力的数据结构。线段树维护区间,每个线段树的结点分别又是一棵平衡树。这样就可以解决任意区间的动态查询前驱问题。

#include <bits/stdc++.h>
using namespace std;
const int N = 5e4+10,INF = 0x3fffffff;
int n,m,op,L,R,X;
int arr[N];
multiset<int> tree[N<<2];
void build(int l,int r,int rt){
    tree[rt].insert(-INF); // 哨兵防越界
    for(int i = l; i <= r; ++i){
        tree[rt].insert(arr[i]);
    }
    if(l==r)return;
    int mid = l+r>>1;
    build(l,mid,rt<<1);
    build(mid+1,r,rt<<1|1);
}

void modify(int l,int r,int rt,int pos,int v){
    tree[rt].erase(tree[rt].find(arr[pos]));
    tree[rt].insert(v);
    if(l==r){
        arr[pos] = v;
    }else{
        int mid = l+r>>1;
        if(pos <= mid){
            modify(l,mid,rt<<1,pos,v);
        }else{
            modify(mid+1,r,rt<<1|1,pos,v);
        }
    }
}


int query(int l,int r,int rt,int ql,int qr,int x){
    if(ql <= l && qr >= r){
        return *--tree[rt].lower_bound(x);
    }else{
        int mid = l+r>>1;
        int ans = -INF;
        if(ql <= mid){
            ans = max(ans,query(l,mid,rt<<1,ql,qr,x));
        }
        if(qr > mid){
            ans = max(ans,query(mid+1,r,rt<<1|1,ql,qr,x));
        }
        return ans;
    }
}


int main(){
    scanf("%d%d",&n,&m);
    for(int i = 1; i <= n; ++i){
        scanf("%d",&arr[i]);
    }
    build(1,n,1);
    while(m--){
        scanf("%d",&op);
        if(op == 1){
            scanf("%d%d",&L,&X);
            modify(1,n,1,L,X);
        }else{
            scanf("%d%d%d",&L,&R,&X);
            printf("%d\n",query(1,n,1,L,R,X));
        }
    }


    // system("pause");
    return 0;
}
posted @ 2021-02-14 21:54  popozyl  阅读(52)  评论(0编辑  收藏  举报