Fhq Treap无旋Treap练习

 

 

 

洛谷p3369 【模板】普通平衡树

split采用按权

/*
    author:revolIA
    submit:;
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+5;
int l[maxn],r[maxn],val[maxn],Size[maxn];
int rom[maxn],cnt;
int root,opt,n,a,x,y,z;
void update(int x){Size[x] = 1+Size[l[x]]+Size[r[x]];}
int New(int x){
    Size[++cnt] = 1;
    val[cnt] = x;
    rom[cnt] = rand() << 15 | rand();
    return cnt;
}
void split(int u,int k,int &x,int &y){
    if(!u){x = y = 0;return;}
    if(val[u]<=k)x = u,split(r[u],k,r[u],y);
    else y = u,split(l[u],k,x,l[u]);
    update(u);
}
int Merge(int x,int y){
    if(x*y == 0)return x+y;
    if(rom[x]<rom[y]){
        r[x] = Merge(r[x],y);
        return update(x),x;
    }else{
        l[y] = Merge(x,l[y]);
        return update(y),y;
    }
}
int K_th(int u,int k){
    if(k<=Size[l[u]])return K_th(l[u],k);
    if(k == Size[l[u]]+1)return u;
    return K_th(r[u],k-Size[l[u]]-1);
}
int main(){
    srand(time(0));
    scanf("%d",&n);
    while(n--){
        scanf("%d%d",&opt,&a);
        if(opt == 1){
            split(root,a,x,y);
            root = Merge(Merge(x,New(a)),y);
        }else if(opt == 2){
            split(root,a,x,z);
            split(x,a-1,x,y);
            y = Merge(l[y],r[y]);//del y(a)
            root = Merge(Merge(x,y),z);
        }else if(opt == 3){
            split(root,a-1,x,y);
            printf("%d\n",Size[x]+1);
            root = Merge(x,y);
        }else if(opt == 4){
            printf("%d\n",val[K_th(root,a)]);
        }else if(opt == 5){
            split(root,a-1,x,y);
            printf("%d\n",val[K_th(x,Size[x])]);
            root = Merge(x,y);
        }else{
            split(root,a,x,y);
            printf("%d\n",val[K_th(y,1)]);
            root = Merge(x,y);
        }
    }
    return 0;
}

 

 

洛谷p3391 文艺平衡树(Splay)

split采用按Size

 

/*
    author:revolIA
    submit:;
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
int l[maxn],r[maxn],val[maxn],Size[maxn];
int rom[maxn],cnt;
int flag[maxn];
int root,opt,n,m,a,x,y,z;
void push_up(int x){Size[x] = 1+Size[l[x]]+Size[r[x]];}
void push_down(int x){
    swap(l[x],r[x]);
    flag[l[x]] ^= 1;
    flag[r[x]] ^= 1;
    flag[x] = 0;
}
int New(int x){
    Size[++cnt] = 1;
    val[cnt] = x;
    rom[cnt] = rand() << 15 | rand();
    return cnt;
}
void split(int u,int k,int &x,int &y){
    if(!u){x = y = 0;return;}
    if(flag[u])push_down(u);
    if(Size[l[u]]<k)x = u,split(r[u],k-Size[l[u]]-1,r[u],y);
    else y = u,split(l[u],k,x,l[u]);
    push_up(u);
}
int Merge(int x,int y){
    if(x*y == 0)return x+y;
    if(rom[x]<rom[y]){
        if(flag[x])push_down(x);
        r[x] = Merge(r[x],y);
        return push_up(x),x;
    }
    if(flag[y])push_down(y);
    l[y] = Merge(x,l[y]);
    return push_up(y),y;
}
void dfs(int u){
    if(!u)return;
    if(flag[u])push_down(u);
    dfs(l[u]);
    printf("%d ",val[u]);
    dfs(r[u]);
}
int main(){
    srand(time(0));
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)root = Merge(root,New(i));
    while(m--){
        int L,R;
        scanf("%d%d",&L,&R);
        split(root,L-1,x,y);
        split(y,R-L+1,y,z);
        flag[y] ^= 1;
        root = Merge(Merge(x,y),z);
    }
    dfs(root);
    return 0;
}

 

 

bzoj1251: 序列终结者

splay很像的操作

Max维护区间最值,lazy区间加,flag区间翻转标记

 

/*
    author:revolIA
    submit:;
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
int l[maxn],r[maxn],val[maxn],Size[maxn];
int rom[maxn],cnt;
int flag[maxn],lazy[maxn],Max[maxn];
int root,opt,n,m,a,x,y,z;
void update(int x,int w){
    val[x] += w;
    lazy[x] += w;
    Max[x] += w;
}
void push_up(int x){
    Size[x] = 1+Size[l[x]]+Size[r[x]];
    Max[x] = val[x];
    if(l[x])Max[x] = max(Max[x],Max[l[x]]);
    if(r[x])Max[x] = max(Max[x],Max[r[x]]);
}
void push_down(int x){
    if(flag[x]){
        swap(l[x],r[x]);
        flag[l[x]] ^= 1;
        flag[r[x]] ^= 1;
        flag[x] = 0;
    }
    if(lazy[x]){
        if(l[x])update(l[x],lazy[x]);
        if(r[x])update(r[x],lazy[x]);
        lazy[x] = 0;
    }
}
int New(int x){
    Size[++cnt] = 1;
    val[cnt] = Max[cnt] = x;
    rom[cnt] = rand() << 15 | rand();
    lazy[cnt] = flag[cnt] = 0;
    return cnt;
}
void split(int u,int k,int &x,int &y){
    if(!u){x = y = 0;return;}
    push_down(u);
    if(Size[l[u]]<k)x = u,split(r[u],k-Size[l[u]]-1,r[u],y);
    else y = u,split(l[u],k,x,l[u]);
    push_up(u);
}
int Merge(int x,int y){
    if(x*y == 0)return x+y;
    if(rom[x]<rom[y]){
        push_down(x);
        r[x] = Merge(r[x],y);
        return push_up(x),x;
    }
    push_down(y);
    l[y] = Merge(x,l[y]);
    return push_up(y),y;
}
int main(){
    srand(time(0));
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)root = Merge(root,New(0));
    while(m--){
        int K,L,R,V;
        scanf("%d%d%d",&K,&L,&R);
        split(root,L-1,x,y);
        split(y,R-L+1,y,z);
        if(K == 1){
            scanf("%d",&V);
            update(y,V);
        }else if(K == 2){
            flag[y] ^= 1;
        }else{
            printf("%d\n",Max[y]);
        }
        root = Merge(Merge(x,y),z);
    }
    return 0;
}

 

 

P3372 【模板】线段树 1

果然,学了一个东西看到啥都想去套一下、

 

/*
    author:revolIA
    submit:;
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
int l[maxn],r[maxn],val[maxn],Size[maxn];
int rom[maxn],cnt;
ll lazy[maxn],Sum[maxn];
int root,opt,n,m,a,x,y,z;
void update(int x,int w){
    val[x] += w;
    lazy[x] += w;
    Sum[x] += w*Size[x];
}
void push_up(int x){
    Size[x] = 1+Size[l[x]]+Size[r[x]];
    Sum[x] = val[x];
    if(l[x])Sum[x] += Sum[l[x]];
    if(r[x])Sum[x] += Sum[r[x]];
}
void push_down(int x){
    if(lazy[x]){
        if(l[x])update(l[x],lazy[x]);
        if(r[x])update(r[x],lazy[x]);
        lazy[x] = 0;
    }
}
int New(int x){
    Size[++cnt] = 1;
    val[cnt] = Sum[cnt] = x;
    rom[cnt] = rand() << 15 | rand();
    lazy[cnt] = 0;
    return cnt;
}
void split(int u,int k,int &x,int &y){
    if(!u){x = y = 0;return;}
    push_down(u);
    if(Size[l[u]]<k)x = u,split(r[u],k-Size[l[u]]-1,r[u],y);
    else y = u,split(l[u],k,x,l[u]);
    push_up(u);
}
int Merge(int x,int y){
    if(x*y == 0)return x+y;
    if(rom[x]<rom[y]){
        push_down(x);
        r[x] = Merge(r[x],y);
        return push_up(x),x;
    }
    push_down(y);
    l[y] = Merge(x,l[y]);
    return push_up(y),y;
}
int main(){
    srand(time(0));
    scanf("%d%d",&n,&m);
    for(int i=1,x;i<=n;i++)scanf("%d",&x),root = Merge(root,New(x));
    while(m--){
        int K,L,R,V;
        scanf("%d%d%d",&K,&L,&R);
        split(root,L-1,x,y);
        split(y,R-L+1,y,z);
        if(K == 1){
            scanf("%d",&V);
            update(y,V);
        }else{
            printf("%lld\n",Sum[y]);
        }
        root = Merge(Merge(x,y),z);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值