BZOJ 2631 tree

LCT

好智障啊,update的条件设成判null了,其实应该是判isroot的……

#include<cstdio>
#include<algorithm>
#define N 100005
#define MOD 51061
using namespace std;
namespace runzhe2000
{
    typedef unsigned uint;
    int n, q;
    struct node
    {
        node *ch[2], *fa;
        uint v, sum, k, b; int rev, siz;
    }mem[N], *tot, *null, *pos[N];
    void init()
    {
        null = tot = mem;
        null->ch[0] = null->ch[1] = null->fa = null;
        null->v = null->sum = null->b = null->rev = null->siz = 0; null->k = 1;
        for(int i = 1; i <= n; i++) pos[i] = ++tot, *pos[i] = *null, pos[i]->v = pos[i]->sum = 1;
    }
    int type(node *x){return x->fa->ch[1]==x?1:0;}
    int isroot(node *x){return x->fa->ch[type(x)] != x;}
    void mswap(node *&x, node *&y){node *t = x; x = y; y = t;}
    void pushup(node *x)
    {
        x->sum = (x->v + x->ch[0]->sum + x->ch[1]->sum) % MOD; 
        x->siz = (x->ch[0]->siz + x->ch[1]->siz + 1) % MOD;
    }
    void pushdown(node *x)
    {
        if(x->rev) 
        {
            x->rev = 0, x->ch[0]->rev ^= 1, x->ch[1]->rev ^= 1;
            mswap(x->ch[0]->ch[0], x->ch[0]->ch[1]);
            mswap(x->ch[1]->ch[0], x->ch[1]->ch[1]);
        }
        for(int i = 0; i <= 1; i++)
        {
            x->ch[i]->v = (x->k * x->ch[i]->v % MOD + x->b) % MOD;
            x->ch[i]->sum = (x->ch[i]->sum * x->k % MOD + x->b * x->ch[i]->siz % MOD) % MOD;
            (x->ch[i]->k *= x->k) %= MOD;
            (x->ch[i]->b *= x->k) %= MOD, (x->ch[i]->b += x->b) %= MOD;
        }
        x->k = 1;  x->b = 0;
    }
    void update(node *x){if(!isroot(x))update(x->fa); pushdown(x);}
    void rotate(node *x)
    {
        node *f = x->fa; int d = type(x);
        x->fa = f->fa, !isroot(f) ? x->fa->ch[type(f)] = x : 0;
        (f->ch[d] = x->ch[d^1]) != null ? f->ch[d]->fa = f : 0;
        f->fa = x, x->ch[d^1] = f; pushup(f);
    }
    void splay(node *x)
    {
        update(x);
        for(; !isroot(x); )
        {
            if(isroot(x->fa)) rotate(x);
            else if(type(x) == type(x->fa)) rotate(x->fa), rotate(x);
            else rotate(x),rotate(x);
        }
        pushup(x);
    }
    void access(node *x)
    {
        node *tmp = null;
        for(; x != null; )
        {
            splay(x);
            x->ch[1] = tmp;
            pushup(x);
            tmp = x;
            x = x->fa;
        }
    }
    void makeroot(node *x)
    {
        access(x);
        splay(x);
        x->rev ^= 1;
        swap(x->ch[0], x->ch[1]);
    }
    void link(node *x, node *y)
    {
        makeroot(x);
        x->fa = y;
    }
    void cut(node *x, node *y)
    {
        makeroot(x); access(y);
        splay(y); y->ch[0] = x->fa = null; 
        pushup(y);
    }
    char str[5];
    void main()
    {
        scanf("%d%d",&n,&q);
        init();
        for(int i = 1; i < n; i++)
        {
            int a, b; scanf("%d%d",&a,&b);
            link(pos[a], pos[b]);
        }
        for(int i = 1; i <= q; i++)
        {
            scanf("%s",str);
            if(str[0] == '*' || str[0] == '+')
            {
                int u, v, c; scanf("%d%d%d",&u,&v,&c);
                makeroot(pos[u]);
                access(pos[v]);
                splay(pos[v]); 
                if(str[0] == '*') 
                {
                    (pos[v]->k *= c) %= MOD;
                    (pos[v]->b *= c) %= MOD;
                    (pos[v]->v *= c) %= MOD;
                    (pos[v]->sum *= c) %= MOD;
                }
                else 
                {   
                    (pos[v]->b += c) %= MOD;
                    (pos[v]->v += c) %= MOD;
                    (pos[v]->sum += c * pos[v]->siz) %= MOD;
                } 
            }
            else if(str[0] == '-')
            {
                int u1, v1, u2, v2; scanf("%d%d%d%d",&u1,&v1,&u2,&v2);
                cut(pos[u1], pos[v1]); 
                link(pos[u2], pos[v2]);
            }
            else
            {
                int u, v; scanf("%d%d",&u,&v);
                makeroot(pos[u]); access(pos[v]);
                splay(pos[v]); 
                printf("%u\n",pos[v]->sum);
            }
        }
    }
}
int main()
{
    runzhe2000::main();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值