洛谷 P1501 [国家集训队]Tree II

洛谷 P1501 [国家集训队]Tree II        <<————————————————点击跳转

这题就是一道LCT模板题

需要注意一个小细节

一看51061挺小的(呵呵)

其实510612=2607225721>2147483647

需要unsigned int

不多说了   上代码:

 

#include<cstdio>
#define Rint register int
using namespace std;
typedef long long LL;
const int N = 100003, mod = 51061;
int sta[N], top;
namespace LCT {
    void swap(int &a, int &b){a ^= b ^= a ^= b;}
    struct Node {
        int v, fa, siz, ch[2], sum, add, mul;
        bool rev;
    } e[N];
    void pushup(int x){
        e[x].sum = (e[e[x].ch[0]].sum + e[e[x].ch[1]].sum + e[x].v) % mod;
        e[x].siz = e[e[x].ch[0]].siz + e[e[x].ch[1]].siz + 1;
    }
    void pushrev(int x){
        e[x].rev ^= 1;
        swap(e[x].ch[0], e[x].ch[1]);
    }
    void pushtag(int x, int add, int mul){
        if(!x) return;
        e[x].sum = ((LL) e[x].sum * mul + (LL) add * e[x].siz) % mod;
        e[x].add = ((LL) e[x].add * mul + add) % mod;
        e[x].v = ((LL) e[x].v * mul + add) % mod;
        e[x].mul = (LL) e[x].mul * mul % mod;
    }
    void pushdown(int x){
        if(e[x].rev){
            e[x].rev = false;
            if(e[x].ch[0]) pushrev(e[x].ch[0]);
            if(e[x].ch[1]) pushrev(e[x].ch[1]);
        }
        pushtag(e[x].ch[0], e[x].add, e[x].mul);
        pushtag(e[x].ch[1], e[x].add, e[x].mul);
        e[x].add = 0; e[x].mul = 1;
    }
    bool nroot(int x){
        return e[e[x].fa].ch[0] == x || e[e[x].fa].ch[1] == x;
    }
    void rotate(int x){
        int y = e[x].fa, z = e[y].fa, zson = e[z].ch[1] == y, yson = e[y].ch[1] == x, B = e[x].ch[yson ^ 1];
        if(nroot(y)) e[z].ch[zson] = x;
        e[x].ch[yson ^ 1] = y;
        e[y].ch[yson] = B;
        if(B) e[B].fa = y;
        e[y].fa = x;
        e[x].fa = z;
        pushup(y);
    }
    void splay(int x){
        int now = x;
        sta[++ top] = x;
        while(nroot(now)) sta[++ top] = now = e[now].fa;
        while(top) pushdown(sta[top --]);
        while(nroot(x)){
            int y = e[x].fa, z = e[y].fa;
            if(nroot(y))
                rotate((e[z].ch[1] == y) ^ (e[y].ch[1] == x) ? x : y);
            rotate(x);
        }
        pushup(x);
    }
    void access(int x){
        for(Rint y = 0;x;y = x, x = e[x].fa){
            splay(x); e[x].ch[1] = y; pushup(x);
        }
    }
    void makeroot(int x){
        access(x); splay(x); pushrev(x);
    }
    int findroot(int x){
        access(x); splay(x);
        while(e[x].ch[0]) {pushdown(x); x = e[x].ch[0];}
        return x;
    }
    void split(int x, int y){
        makeroot(x); access(y); splay(y);
    }
    void link(int x, int y){
        makeroot(x);
        e[x].fa = y;
    }
    void cut(int x, int y){
        makeroot(x);
        if(findroot(y) == x && e[x].fa == y && !e[x].ch[1]){
            e[x].fa = e[y].ch[0] = 0;
            pushup(y);
        }
    }
}
using namespace LCT;
int n, q;
int main(){
    scanf("%d%d", &n, &q);
    for(Rint i = 1;i <= n;i ++)
        e[i].v = e[i].sum = e[i].mul = 1;
    for(Rint i = 1;i < n;i ++){
        int a, b;
        scanf("%d%d", &a, &b);
        link(a, b);
    }
    while(q --){
        char opt[5];
        scanf("%s", opt);
        int a, b, c, d;
        switch(opt[0]){
            case '+':
                scanf("%d%d%d", &a, &b, &c);
                split(a, b);
                pushtag(b, c, 1);
                break;
            case '-':
                scanf("%d%d%d%d", &a, &b, &c, &d);
                cut(a, b); link(c, d);
                break;
            case '*':
                scanf("%d%d%d", &a, &b, &c);
                split(a, b);
                pushtag(b, 0, c);
                break;
            case '/':
                scanf("%d%d", &a, &b);
                split(a, b);
                printf("%d\n", e[b].sum);
        }
    }
}

 

posted @ 2019-06-06 16:08  骁哥  阅读(230)  评论(0编辑  收藏  举报