萌新刚学OI,FHQ 爆蛋求助/kel

P3391 【模板】文艺平衡树

UperFicial @ 2021-06-17 18:08:29

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#include<cstring>
#include<ctime>
#include<cstdlib>
#include<cctype>
#include<stack>
#include<map>
#include<set>
using namespace std;
inline int read()
{
    int s=0,w=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')s=s*10+(ch-'0'),ch=getchar();
    return s*w;
}
inline void output(int x)
{
    if(x/10) output(x/10);
    putchar(x%10+'0');
    return;
}
const int INF=1e9;
typedef long long ll;
inline int Min(int x,int y){return x<y?x:y;}
inline int Max(int x,int y){return x>y?x:y;}
inline void Swap(int&x,int&y){x^=y;y^=x;x^=y;}
const int MAXN(1e5+10);
int n,m;
int ch[MAXN][2],val[MAXN],siz[MAXN],rnd[MAXN];
int tot,rt,x,y,z;
bool tag[MAXN];
inline int New(int v)
{
    val[++tot]=v;
    siz[tot]=1;
    rnd[tot]=rand();
    tag[tot]=false;
    return tot;
}
inline void push_up(int u)
{
    siz[u]=siz[ch[u][0]]+siz[ch[u][1]]+1;
    return;
}
inline void push_down(int u)
{
    tag[u]=false;
    Swap(ch[u][0],ch[u][1]);
    tag[ch[u][0]]^=1;
    tag[ch[u][1]]^=1; 
    return;
}
inline void split(int u,int v,int&x,int&y)
{
    if(!u) x=y=0;
    else 
    {
        if(tag[u]) push_down(u);
        if(val[u]<=v) x=u,split(ch[u][1],v,ch[u][1],y);
        else y=u,split(ch[u][0],v,x,ch[u][0]);
        push_up(u);
    }
    return;
}
inline int unite(int x,int y)
{
    if(!x||!y) return x+y;
    if(rnd[x]<rnd[y])
    {
        if(tag[x]) push_down(x);
        ch[x][1]=unite(ch[x][1],y);
        push_up(x);
        return x;
    }
    else 
    {
        if(tag[y]) push_down(y);
        ch[y][0]=unite(x,ch[y][0]);
        push_up(y);
        return y;
    }
}
inline void ins(int v)
{
    split(rt,v,x,y);
    rt=unite(unite(x,New(v)),y);
    return;
}
inline void rev(int l,int r)
{
    split(rt,l-1,x,y);
    split(y,r,y,z);
    tag[y]^=1;
    rt=unite(x,unite(y,z));
    return;
}
inline void dfs(int u)
{
    if(!u) return;
    if(tag[u]) push_down(u);
    dfs(ch[u][0]);
    printf("%d ",val[u]);
    dfs(ch[u][1]);
    return;
}
int main()
{
    srand(time(0));
    n=read(),m=read();
    for(register int i=1;i<=n;i++) ins(i);
    while(m--)
    {
        int l=read(),r=read();
        rev(l,r);
        dfs(rt);
        puts("");
    }
    dfs(rt);
    return 0;
}

by UperFicial @ 2021-06-17 18:09:32

最后几行的测试请不要在意,测评的时候都删了


by koishi_offical @ 2021-06-17 18:21:34

@UperFicial 兄啊你文艺平衡树怎么能按权值分裂呢


by koishi_offical @ 2021-06-17 18:22:41

@第114514恋厨 应该按大小分裂


by Acc_Robin @ 2021-06-17 18:24:05

你插入时候的 split 裂了个寂寞

或许 pushdown 的时候需要判断一下是否存在两个儿子?


by Acc_Robin @ 2021-06-17 18:24:44

赞同楼上,不能按权值分裂


by fanypcd @ 2021-06-17 18:29:14

@UperFicial 按排名分裂


by UperFicial @ 2021-06-17 18:30:57

@Acc_Robin @第114514恋厨 @fanypcd

我是想按权值裂成一棵值域在 [l,r] 之间的子树啊


by fanypcd @ 2021-06-17 18:31:40

inline void split_by_rank(int u,int rk,int&x,int&y)
{
    if(!u) x=y=0;
    else 
    {
        if(tag[u]) push_down(u);//其实可以在 pushdown 里面判断的,少写一行 if。
        if(siz[ch[u][0]] + 1 <= rk) x=u,split(ch[u][1],v,ch[u][1],y);
        else y=u,split(ch[u][0],v,x,ch[u][0]);
        push_up(u);
    }
    return;
}

by UperFicial @ 2021-06-17 18:32:21

先按权值 l-1 分成两棵树,右边的那棵树再按 r 分成左右两棵树,左边的那个的值域就在 [l,r] 之间了吧


by koishi_offical @ 2021-06-17 18:33:06

@UperFicial 谁说是值域啊啊啊啊啊啊啊


| 下一页