[国家集训队2012]tree(伍一鸣)

来源:互联网 发布:ios上玩的编程游戏 编辑:程序博客网 时间:2024/05/21 01:53

题目链接,直接 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;}
0 0