luogu3380 模板二逼平衡树(树套树)

Posted poorpool

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu3380 模板二逼平衡树(树套树)相关的知识,希望对你有一定的参考价值。

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <ctime>
using namespace std;
int n, m, cnt, a[50005], rot[200005], opt, ans, uu, vv, ww;
struct Node{
    int l, r, siz, hav, val, rnd;
}nd[4000005];
void upd(int k){
    nd[k].siz = nd[nd[k].l].siz + nd[nd[k].r].siz + nd[k].hav;
}
void lRotate(int &k){
    int t=nd[k].r; nd[k].r = nd[t].l; nd[t].l = k;
    nd[t].siz = nd[k].siz; upd(k); k = t;
}
void rRotate(int &k){
    int t=nd[k].l; nd[k].l = nd[t].r; nd[t].r = k;
    nd[t].siz = nd[k].siz; upd(k); k = t;
}
void treapInsert(int &k, int x){
    if(!k){
        k = ++cnt; nd[k].siz = nd[k].hav = 1;
        nd[k].val = x; nd[k].rnd = rand();
        return ;
    }
    nd[k].siz++;
    if(nd[k].val==x)    nd[k].hav++;
    else if(nd[k].val>x){
        treapInsert(nd[k].l, x);
        if(nd[nd[k].l].rnd<nd[k].rnd)   rRotate(k);
    }
    else{
        treapInsert(nd[k].r, x);
        if(nd[nd[k].r].rnd<nd[k].rnd)   lRotate(k);
    }
}
void treapDelete(int &k, int x){
    if(!k)  return ;
    if(nd[k].val==x){
        if(nd[k].hav>1){
            nd[k].hav--; nd[k].siz--;
            return ;
        }
        else if(nd[k].l*nd[k].r==0) k = nd[k].l + nd[k].r;
        else if(nd[nd[k].l].rnd<nd[nd[k].r].rnd)
            rRotate(k), treapDelete(k, x);
        else
            lRotate(k), treapDelete(k, x); 
    }
    else if(nd[k].val<x)    nd[k].siz--, treapDelete(nd[k].r, x);
    else    nd[k].siz--, treapDelete(nd[k].l, x);
}
int treapQueryRank(int k, int x){
    if(!k)  return 0;
    if(nd[k].val>x) return treapQueryRank(nd[k].l, x);
    else if(nd[k].val<x)    return treapQueryRank(nd[k].r, x)+nd[nd[k].l].siz+nd[k].hav;
    else    return nd[nd[k].l].siz;
}
void treapQueryPre(int k, int x){
    if(!k)  return ;
    if(nd[k].val<x) ans = max(ans, nd[k].val), treapQueryPre(nd[k].r, x);
    else    treapQueryPre(nd[k].l, x);
} 
void treapQueryNxt(int k, int x){
    if(!k)  return ;
    if(nd[k].val>x) ans = min(ans, nd[k].val), treapQueryNxt(nd[k].l, x);
    else    treapQueryNxt(nd[k].r, x);
} 
void sgtInsert(int o, int l, int r, int x, int k){
    treapInsert(rot[o], k);
    if(l==r)    ;
    else{
        int mid=(l+r)>>1;
        int lson=o<<1;
        int rson=lson|1;
        if(x<=mid)  sgtInsert(lson, l, mid, x, k);
        if(mid<x)   sgtInsert(rson, mid+1, r, x, k);
    }
}
void sgtDelete(int o, int l, int r, int x, int k){
    treapDelete(rot[o], k);
    if(l==r)    ;
    else{
        int mid=(l+r)>>1;
        int lson=o<<1;
        int rson=lson|1;
        if(x<=mid)  sgtDelete(lson, l, mid, x, k);
        if(mid<x)   sgtDelete(rson, mid+1, r, x, k);
    }
}
int sgtQueryRank(int o, int l, int r, int x, int y, int k){
    if(l>=x && r<=y)    return treapQueryRank(rot[o], k);
    else{
        int mid=(l+r)>>1;
        int lson=o<<1;
        int rson=lson|1;
        int re=0;
        if(x<=mid)  re += sgtQueryRank(lson, l, mid, x, y, k);
        if(mid<y)   re += sgtQueryRank(rson, mid+1, r, x, y, k);
        return re;
    }
}
void sgtQueryPre(int o, int l, int r, int x, int y, int k){
    if(l>=x && r<=y)    treapQueryPre(rot[o], k);
    else{
        int mid=(l+r)>>1;
        int lson=o<<1;
        int rson=lson|1;
        if(x<=mid)  sgtQueryPre(lson, l, mid, x, y, k);
        if(mid<y)   sgtQueryPre(rson, mid+1, r, x, y, k);
    }
}
void sgtQueryNxt(int o, int l, int r, int x, int y, int k){
    if(l>=x && r<=y)    treapQueryNxt(rot[o], k);
    else{
        int mid=(l+r)>>1;
        int lson=o<<1;
        int rson=lson|1;
        if(x<=mid)  sgtQueryNxt(lson, l, mid, x, y, k);
        if(mid<y)   sgtQueryNxt(rson, mid+1, r, x, y, k);
    }
}
int queryKth(int uu, int vv, int ww){
    int l=0, r=100000000, mid, re;
    while(l<=r){
        mid = (l + r) >> 1;
        if(sgtQueryRank(1, 1, n, uu, vv, mid)+1<=ww)    re = mid, l = mid + 1;
        else    r = mid - 1;
    }
    return re;
}
int main(){
    srand(time(NULL));
    cin>>n>>m;
    for(int i=1; i<=n; i++){
        scanf("%d", &a[i]);
        sgtInsert(1, 1, n, i, a[i]);
    }
    while(m--){
        scanf("%d", &opt);
        if(opt==1){
            scanf("%d %d %d", &uu, &vv, &ww);
            printf("%d\n", sgtQueryRank(1, 1, n, uu, vv, ww)+1);
        }
        if(opt==2){
            scanf("%d %d %d", &uu, &vv, &ww);
            printf("%d\n", queryKth(uu, vv, ww));
        }
        if(opt==3){
            scanf("%d %d", &uu, &vv);
            sgtDelete(1, 1, n, uu, a[uu]);
            a[uu] = vv;
            sgtInsert(1, 1, n, uu, vv);
        }
        if(opt==4){
            scanf("%d %d %d", &uu, &vv, &ww);
            ans = -2147483647;
            sgtQueryPre(1, 1, n, uu, vv, ww);
            printf("%d\n", ans);
        }
        if(opt==5){
            scanf("%d %d %d", &uu, &vv, &ww);
            ans = 2147483647;
            sgtQueryNxt(1, 1, n, uu, vv, ww);
            printf("%d\n", ans);
        }
    }
    return 0;
}

以上是关于luogu3380 模板二逼平衡树(树套树)的主要内容,如果未能解决你的问题,请参考以下文章

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

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

洛谷 P3380 模板二逼平衡树(树套树)

[模板]洛谷T3380 二逼平衡树 线段树套Splay

洛谷P3380 模板二逼平衡树(树套树,树状数组,线段树)

洛谷3380 二逼平衡树(树套树)