P1501 [国家集训队]Tree II LCT

链接

luogu

思路

简单题

代码

#include <bits/stdc++.h>
#define ls c[x][0]
#define rs c[x][1]
using namespace std;
const int N = 1e5 + 7, mod = 51061;
int read() {
    int x = 0, f = 1; char s = getchar();
    for (;s > '9' || s < '0'; s = getchar()) if (s == '-') f = -1;
    for (;s >= '0' && s <= '9'; s = getchar()) x = x * 10 + s - '0';
    return x * f;
}
int f[N], c[N][2], w[N], siz[N], lazy[N], stak[N];
int add[N], mul[N], sum[N];
bool isroot(int x) {return c[f[x]][0] == x || c[f[x]][1] == x;}
void tag(int x) {swap(ls, rs), lazy[x] ^= 1;}
void tag1(int x, int ad) {
    add[x] = (add[x] + ad) % mod;
    sum[x] = (sum[x] + 1LL * ad * siz[x] % mod) % mod;
    w[x] = (w[x] + ad) % mod;
}
void tag2(int x, int mu) {
    mul[x] = 1LL * mul[x] * mu % mod;
    add[x] = 1LL * add[x] * mu % mod;
    sum[x] = 1LL * sum[x] * mu % mod;
    w[x] = 1LL * w[x] * mu % mod;
}
void pushup(int x) {
    sum[x] = (sum[ls] + sum[rs] + w[x]) % mod;
    siz[x] = siz[ls] + siz[rs] + 1;
}
void pushdown(int x) {
    if (lazy[x]) {
        if (ls) tag(ls);
        if (rs) tag(rs);
        lazy[x] ^= 1;
    }
    if (mul[x] != 1) {
        if (ls) tag2(ls, mul[x]);
        if (rs) tag2(rs, mul[x]);
        mul[x] = 1;
    }
    if (add[x]) {
        if (ls) tag1(ls, add[x]);
        if (rs) tag1(rs, add[x]);
        add[x] = 0;
    }
}
void rotate(int x) {
    int y = f[x], z = f[y], k = c[y][1] == x, w = c[x][!k];
    if (isroot(y)) c[z][c[z][1] == y] = x;
    c[x][!k] = y;
    c[y][k] = w;
    if (w) f[w] = y;
    f[x] = z;
    f[y] = x;
    pushup(y);
}
void splay(int x) {
    int y = x, z = 0;
    stak[++z] = y;
    while (isroot(y)) stak[++z] = y = f[y];
    while (z) pushdown(stak[z--]);
    while (isroot(x)) {
        y = f[x], z = f[y];
        if (isroot(y)) rotate((c[y][0] == x)^(c[z][0] == y) ? x : y);
        rotate(x);
    }
    pushup(x);
}
void access(int x) {
    for (int y = 0; x;x = f[y = x])
        splay(x), rs = y, pushup(x);
}
void makeroot(int x) {
    access(x), splay(x), tag(x);
}
int findroot(int x) {
    access(x), splay(x);
    while(ls) pushdown(x), x = ls;
    return x;
}
void split(int x, int y) {
    makeroot(x), access(y), splay(y);
}
void link(int x, int y) {
    makeroot(x);
    if (findroot(y) != x) f[x] = y;
}
void cut(int x, int y) {
    makeroot(x);
    if (findroot(y) == x && f[x] == y && !rs) {
        f[x] = c[y][0] = 0;
        pushup(y);
    }
}
int main() {    
    int n = read(), q = read();
    for (int i = 1; i <= n; ++i) w[i] = mul[i] = 1;
    for (int i = 1; i < n; ++i) {
        int u = read(), v = read();
        link(u, v);
    }
    char s[10];
    for (int i = 1; i <= q; ++i) {
        scanf("%s", s);
        if (s[0] == '+') {
            int u = read(), v = read(), c = read();
            split(u, v), tag1(v, c);
        }
        if (s[0] == '-') {
            int u = read(), v = read(), u1 = read(), v1 = read();
            cut(u, v),link(u1, v1);
        }
        if (s[0] == '*') {
            int u = read(), v = read(), c = read();
            split(u, v), tag2(v, c);
        }
        if (s[0] == '/') {
            int u = read(), v = read();
            split(u, v), printf("%d\n", sum[v]);
        }
    }
    return 0;
}
全部评论

相关推荐

06-27 12:30
延安大学 C++
实习+外包,这两个公司底层融为一体了,如何评价呢?
一表renzha:之前面了一家外包的大模型,基本上都能答出来,那面试官感觉还没我懂,然后把我挂了,我都还没嫌弃他是外包,他把我挂了……
点赞 评论 收藏
分享
Southyeung:我说一下我的看法(有冒犯实属抱歉):(1)简历不太美观,给我一种看都不想看的感觉,感觉字体还是排版问题;(2)numpy就一个基础包,机器学习算法是什么鬼?我感觉你把svm那些写上去都要好一点。(2)课程不要写,没人看,换成获奖经历;(3)项目太少了,至少2-3个,是在不行把网上学习的也写上去。
点赞 评论 收藏
分享
每晚夜里独自颤抖:把华北改为华南再试一试,应该就没啥问题了。改完可能都不用投,别人主动联系了。
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务