[國家集訓隊2012]tree(伍一鳴)


題目鏈接,直接 LCT 就好,注意取模,還有數據很強,510612 會爆 int


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <vector>
#include <utility>
#include <stack>
#include <queue>
#include <iostream>
#include <algorithm>

template<class Num>void read(Num &x)
{
    char c; int flag = 1;
    while((c = getchar()) < '0' || c > '9')
        if(c == '-') flag *= -1;
    x = c - '0';
    while((c = getchar()) >= '0' && c <= '9')
        x = (x<<3) + (x<<1) + (c-'0');
    x *= flag;
    return;
}
template<class Num>void write(Num x)
{
    if(!x) {putchar('0');return;}
    if(x < 0) putchar('-'), x = -x;
    static char s[20];int sl = 0;
    while(x) s[sl++] = x%10 + '0',x /= 10;
    while(sl) putchar(s[--sl]);
}

const int maxn = 1e5 + 50, maxq = maxn;
const int INF = 0x3f3f3f3f, Nya = -1;
const int Mod = 51061;

int n, m, q;
unsigned int val[maxn], sum[maxn];
int size[maxn];
unsigned int mul[maxn], add[maxn];

namespace LCT
{
    int c[maxn][2], fa[maxn];
    int rev[maxn];

    void update(int x)
    {
        sum[x] = (sum[c[x][0]] + sum[c[x][1]] + val[x]) % Mod;
        size[x] = size[c[x][0]] + size[c[x][1]] + 1;
    }
    void _mul(int v,int x)
    {
        val[v] = (val[v] * x) % Mod;
        sum[v] = (sum[v] * x) % Mod;
        mul[v] = (mul[v] * x) % Mod;
        add[v] = (add[v] * x) % Mod;
    }
    void _add(int v,int x)
    {
        val[v] = (val[v] + x) % Mod;
        sum[v] = (sum[v] + x * size[v]) % Mod;
        add[v] = (add[v] + x) % Mod;    
    }
    void pushdown(int x)
    {
        int v;

        if(rev[x])
        {
            rev[c[x][0]] ^= 1;
            rev[c[x][1]] ^= 1;
            std::swap(c[x][0], c[x][1]);
            rev[x] = 0;
        }
        if(mul[x] != 1)
        {
            if(c[x][0]) _mul(c[x][0], mul[x]);
            if(c[x][1]) _mul(c[x][1], mul[x]);

            mul[x] = 1;
        }
        if(add[x])
        {
            if(c[x][0]) _add(c[x][0], add[x]);
            if(c[x][1]) _add(c[x][1], add[x]);

            add[x] = 0;
        }
    }
    bool isroot(int x)
    {
        return x != c[fa[x]][0] && x != c[fa[x]][1];
    }
    void rotate(int x)
    {
        int y = fa[x], z = fa[y], i, j;

        pushdown(y), pushdown(x);
        j = (c[z][1] == y), i = (c[y][1] == x);

        if(!isroot(y)) c[z][j] = x;
        else fa[x] = fa[y], fa[y] = 0;

        if(c[x][i^1]) fa[c[x][i^1]] = y;
        fa[x] = z, fa[y] = x;
        c[y][i] = c[x][i^1], c[x][i^1] = y;

        update(y), update(x); 
    }
    void Splay(int v)
    {
        int g = fa[v], h = fa[g];

        pushdown(v);

        while(!isroot(v))
        {
            if(!isroot(g)) 
            {
                if((c[h][1] == g)^(c[g][1] == v))
                    rotate(v);
                else
                    rotate(g);
            }
            rotate(v), g = fa[v], h = fa[g];    
        }

        update(v);
    }
    void access(int v)
    {
        int u = v, e = v;
        v = 0;

        while(u)
        {
            Splay(u);

            int &t = c[u][1];

            t = v, update(u);
            v = u, u = fa[u];
        }
        Splay(e);
    }
    void makeroot(int v)
    {
        access(v);
        rev[v] ^= 1;
    }
    void join(int v,int u)
    {
        makeroot(v);
        fa[v] = u;
        access(v);
    }
    void cut(int v,int u)
    {
        makeroot(v);
        access(u);
        c[u][0] = fa[v] = 0;
    }
}
void init()
{
    int u, v;
    read(n), read(q);

    for(int i = 1; i <= n; i++)
        sum[i] = val[i] = mul[i] = size[i] = 1;

    for(int i = 1; i < n; i++)
        read(u), read(v), LCT::join(u, v);
}
void solve()
{
    char str[5];
    int u, v, x, y;

    while(q--)
    {
        scanf("%s", str);

        if(str[0] == '+')
        {
            read(u), read(v), read(x);
            LCT::makeroot(u), LCT::access(v), LCT::_add(v, x);
        }
        else if(str[0] == '-')
        {
            read(u), read(v), read(x), read(y);
            LCT::cut(u, v), LCT::join(x, y);
        }
        else if(str[0] == '*')
        {
            read(u), read(v), read(x);
            LCT::makeroot(u), LCT::access(v), LCT::_mul(v, x);
        }
        else if(str[0] == '/')
        {
            read(u), read(v);
            LCT::makeroot(u), LCT::access(v);
            write(sum[v]), puts("");
        }
        else
            std::cerr << "error!";
    }
}

int main()
{
    freopen("nt2012_wym_tree.in","r",stdin);
    freopen("nt2012_wym_tree.out","w",stdout);

    init();

    solve();

    fclose(stdin);
    fclose(stdout);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章