hdu4942 Game on S♂play【线段树 or LCT】

题目大意:

给一棵二叉树,每个点有权值,定义每个点的size为其子树的权值和,每个点的有趣值为其子树内size值之积。要求支持左旋右旋操作(就像splay上一样),或是询问某个点的有趣值。

解题思路:

1.先说一下LCT的做法:
注意到每次旋转只会改变两个点(x,y)的size值,然后改变其父亲的有趣值(除以原来y的有趣值,乘以x新的有趣值),所以可以用LCT模拟旋转操作及维护每个点的有趣值。码量极大。而且要点权不为0才行(不然除0就gg了),所以不能过本题。不过还是贴了份代码,以供dalao们参观。

2.线段树做法:
注意到对于平衡树来说不论如何旋转,其中序遍历不会改变,且子树的中序遍历序仍是一段连续的区间,所以我们只要用中序遍历序建线段树,维护每个点的size值,询问时区间求积即可。(注意旋转操作会改变两个点子树的区间,操作时修改即可,详见代码update函数)。

线段树:

#include<bits/stdc++.h>
#define ll long long
using namespace std;

int getint()
{
    int i=0,f=1;char c;
    for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar());
    if(c=='-')c=getchar(),f=-1;
    for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
    return i*f;
}

const int N=200005,mod=1e9+7;
int T,n,m,tot;
int son[N][2],fa[N],val[N],size[N],mul[N<<2];
int in[N],out[N],pos[N],idx[N];

void dfs(int u,int f)
{
    if(!u)return;
    fa[u]=f,in[u]=tot+1;
    dfs(son[u][0],u);
    pos[u]=++tot,idx[tot]=u;
    dfs(son[u][1],u);
    out[u]=tot;
    size[u]=(val[u]+(size[son[u][0]]+size[son[u][1]])%mod)%mod;
}

void build(int k,int l,int r)
{
    if(l==r)
    {
        mul[k]=size[idx[l]];
        return;
    }
    int mid=l+r>>1;
    build(k<<1,l,mid),build(k<<1|1,mid+1,r);
    mul[k]=1ll*mul[k<<1]*mul[k<<1|1]%mod;
}

void modify(int k,int l,int r,int p,int v)
{
    if(l==r)
    {
        mul[k]=v;
        return;
    }
    int mid=l+r>>1;
    if(p<=mid)modify(k<<1,l,mid,p,v);
    else modify(k<<1|1,mid+1,r,p,v);
    mul[k]=1ll*mul[k<<1]*mul[k<<1|1]%mod;
}

int query(int k,int l,int r,int x,int y)
{
    if(x==l&&y==r)return mul[k];
    int mid=l+r>>1;
    if(y<=mid)return query(k<<1,l,mid,x,y);
    else if(x>mid)return query(k<<1|1,mid+1,r,x,y);
    else return 1ll*query(k<<1,l,mid,x,mid)*query(k<<1|1,mid+1,r,mid+1,y)%mod;
}

int which(int x)
{
    return son[fa[x]][1]==x;
}

void update(int x)
{
    in[x]=son[x][0]?in[son[x][0]]:pos[x];
    out[x]=son[x][1]?out[son[x][1]]:pos[x];
}

void Rotate(int x)
{
    int y=fa[x],z=fa[y],t=which(x);
    if(z)son[z][which(y)]=x;
    fa[x]=z,fa[y]=x;
    son[y][t]=son[x][t^1],son[x][t^1]=y;
    if(son[y][t])fa[son[y][t]]=y;
    size[x]=size[y];
    size[y]=(val[y]+(size[son[y][0]]+size[son[y][1]])%mod)%mod;
    update(y),update(x);
    modify(1,1,n,pos[x],size[x]),modify(1,1,n,pos[y],size[y]);
}

void clear()
{
    tot=0;
    memset(son,0,sizeof(son));
    memset(fa,0,sizeof(fa));
}

int main()
{
    //freopen("splay.in","r",stdin);
    //freopen("splay.out","w",stdout);
    T=getint();
    for(int C=1;C<=T;C++)
    {
        printf("Case #%d:\n",C);
        clear();
        int op,x;
        n=getint(),m=getint();
        for(int i=1;i<=n;i++)
            val[i]=getint(),son[i][0]=getint(),son[i][1]=getint();
        dfs(1,0);build(1,1,n);
        while(m--)
        {
            op=getint(),x=getint();
            if(op==2)printf("%d\n",query(1,1,n,in[x],out[x]));
            else 
            {
                x=son[x][op];
                if(!x)continue;
                Rotate(x);
            }
        }
    }
    return 0;
}

LCT:

#include<bits/stdc++.h>
#define ll long long
using namespace std;

int getint()
{
    int i=0,f=1;char c;
    for(c=getchar();(c!='-')&&(c<'0'||c>'9');c=getchar());
    if(c=='-')c=getchar(),f=-1;
    for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
    return i*f;
}

const int N=200005,p=1e9+7;
int T,n,m;
int root,Son[N][2],Fa[N],val[N],size[N],mul[N];
int son[N][2],fa[N],rev[N],stk[N],tag[N];

void clear()
{
    root=1;
    memset(Son,0,sizeof(Son));
    memset(Fa,0,sizeof(Fa));
    memset(val,0,sizeof(val));
    memset(size,0,sizeof(size));
    memset(son,0,sizeof(son));
    memset(fa,0,sizeof(fa));
    memset(rev,0,sizeof(rev));
}

int which(int x)
{
    return son[fa[x]][1]==x;
}

bool rt(int x)
{
    return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;
}

void pushdown(int x)
{
    if(rev[x])
    {
        swap(son[x][0],son[x][1]);
        if(son[x][0])rev[son[x][0]]^=1;
        if(son[x][1])rev[son[x][1]]^=1;
        rev[x]=0;
    }
    if(tag[x]!=1)
    {
        mul[x]=(ll)mul[x]*tag[x]%p;
        if(son[x][0])tag[son[x][0]]=(ll)tag[son[x][0]]*tag[x]%p;
        if(son[x][1])tag[son[x][1]]=(ll)tag[son[x][1]]*tag[x]%p;
        tag[x]=1;
    }
}

void rotate(int x)
{
    int y=fa[x],z=fa[y],t=which(x);
    if(!rt(y))son[z][which(y)]=x;
    fa[x]=z,fa[y]=x;
    son[y][t]=son[x][t^1],son[x][t^1]=y;
    if(son[y][t])fa[son[y][t]]=y;
}

void splay(int x)
{
    int top=0;
    stk[++top]=x;
    for(int i=x;!rt(i);i=fa[i])stk[++top]=fa[i];
    for(int i=top;i;i--)pushdown(stk[i]);
    while(!rt(x))
    {
        if(!rt(fa[x]))
            which(x)==which(fa[x])?rotate(fa[x]):rotate(x);
        rotate(x);
    }
}

void access(int x)
{
    for(int y=0;x;y=x,x=fa[x])
    {
        splay(x),son[x][1]=y;
        if(y)fa[y]=x;
    }
}

void makeroot(int x)
{
    access(x),splay(x);
    rev[x]^=1;
}

void link(int x,int y)
{
    makeroot(x),fa[x]=y;
}

void cut(int x,int y)
{
    makeroot(x),access(y),splay(y);
    son[y][0]=fa[x]=0;
}

int Pow(int x,int y)
{
    int res=1;
    for(;y;y>>=1,x=(ll)x*x%p)
        if(y&1)res=(ll)res*x%p;
    return res;
}

void update(int u)
{
    mul[u]=size[u]=((size[Son[u][0]]+size[Son[u][1]])%p+val[u])%p;
    if(Son[u][0])splay(Son[u][0]),mul[u]=(ll)mul[u]*mul[Son[u][0]]%p;
    if(Son[u][1])splay(Son[u][1]),mul[u]=(ll)mul[u]*mul[Son[u][1]]%p;
}

void dfs(int u)
{
    tag[u]=1;
    if(Son[u][0])Fa[Son[u][0]]=fa[Son[u][0]]=u,dfs(Son[u][0]);
    if(Son[u][1])Fa[Son[u][1]]=fa[Son[u][1]]=u,dfs(Son[u][1]);
    update(u);  
}

int Which(int x)
{
    return Son[Fa[x]][1]==x;
}

void Rotate(int x)
{
    int y=Fa[x],z=Fa[y],t=Which(x);
    if(y==root)splay(x),splay(y),root=x;
    else Son[z][Which(y)]=x,cut(y,z),link(x,z);
    Fa[x]=z,Fa[y]=x;
    Son[y][t]=Son[x][t^1],Son[x][t^1]=y;;
    if(Son[y][t])cut(x,Son[y][t]),link(y,Son[y][t]),Fa[Son[y][t]]=y;
    int tmp=Pow(mul[y],p-2);
    update(y),update(x);
    tmp=(ll)tmp*mul[x]%p;
    if(z)makeroot(root),access(z),splay(z),tag[z]=(ll)tag[z]*tmp%p;
}

int query(int x)
{
    splay(x);
    return mul[x];
}

int main()
{
    //freopen("lx.in","r",stdin);
    //freopen("lx.out","w",stdout);
    T=getint();
    for(int C=1;C<=T;C++)
    {
        printf("Case #%d:\n",C);
        clear();
        n=getint(),m=getint();
        for(int i=1;i<=n;i++)
            val[i]=getint(),Son[i][0]=getint(),Son[i][1]=getint();
        dfs(1);
        int op,x;
        while(m--)
        {
            op=getint(),x=getint();
            if(op<2){if(Son[x][op])Rotate(Son[x][op]);}
            else printf("%d\n",query(x));
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值