萌新求调,就过了#1#2#3#11
查看原帖
萌新求调,就过了#1#2#3#11
1088224
LittleYoo楼主2024/4/10 19:20
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;
const int INF = 0x3FFFFFFF;
// const int mod=1e9+7;
typedef long long int64;
typedef vector<int> vi;
typedef pair<int, int> pii;
int n, q, rt, mod;
int val[MAXN]; // 节点的值(初始序号)
vi edge[MAXN];
int dep[MAXN];  // 节点深度
int par[MAXN];  // 节点父亲
int son[MAXN];  // 节点重儿子
int size[MAXN]; // 子树大小
int id[MAXN];   // dfs序id
int nval[MAXN]; // 节点的值(dfs序序号)
int top[MAXN];  // 节点所在链的顶端
struct node
{
    int l, r;
    int64 sum;
    int64 add = 0;
} tr[MAXN * 4];
void dfs1(int now, int p, int d)
{
    par[now] = p;
    dep[now] = d;
    size[now] = 1;
    if (edge[now].size() == 1 && now != rt)
    {
        // 叶子节点
        return;
    }
    for (auto &u : edge[now])
    {
        if (u == par[now])
            continue;
        dfs1(u, now, d + 1);
        size[now] += size[u];

        if (size[u] > size[son[now]])
            son[now] = u;
    }
}
int cnt = 0;
void dfs2(int now, int topp)
{
    top[now] = topp;
    id[now] = ++cnt;
    nval[cnt] = val[now];
    if (!son[now])
        return;
    dfs2(son[now], topp);
    for (auto &u : edge[now])
    {
        if (u == son[now] || u == par[now])
            continue;
        dfs2(u, u);
    }
}

//----------------------------------------
inline void pushup(int now)
{
    tr[now].sum = (tr[now << 1].sum + tr[now << 1 | 1].sum) % mod;
}
inline void calc(int now, int k)
{
    tr[now].sum = (tr[now].sum + k * (tr[now].r - tr[now].l + 1)) % mod;
    tr[now].add = (tr[now].add + k) % mod;
}
inline void pushdown(int now)
{
    calc(now << 1, tr[now].add%mod);
    calc(now << 1 | 1, tr[now].add%mod);
    tr[now].add = 0;
}
void buildtree(int now, int l, int r)
{
    tr[now].l = l;
    tr[now].r = r;
    if (l == r)
    {
        tr[now].sum = nval[l] % mod;
        return;
    }
    int mid = (l + r) >> 1;
    buildtree(now << 1, l, mid);
    buildtree(now << 1 | 1, mid + 1, r);
    pushup(now);
}

void addtoSegment(int now, int l, int r, int k)
{
    if (l <= tr[now].l && r >= tr[now].r)
    {
        calc(now, k%mod);
        return;
    }
    pushdown(now);
    int mid = (tr[now].l + tr[now].r) >> 1;
    if (l <= mid)
        addtoSegment(now << 1, l, r, k);
    if (r > mid)
        addtoSegment(now << 1 | 1, l, r, k);
    pushup(now);
}

int query(int now, int l, int r)
{
    if (l <= tr[now].l && r >= tr[now].r)
        return tr[now].sum % mod;
    pushdown(now);
    int mid = (tr[now].l + tr[now].r) >> 1;
    int64 ret = 0;
    if (l <= mid)
        ret = (ret + query(now << 1, l, r)) % mod;
    if (r > mid)
        ret = (ret + query(now << 1 | 1, l, r)) % mod;
    return ret;
}
//----------------------------------------
void addtoPath(int u, int v, int k)
{

    if (top[u] == top[v])
    {
        if (id[u] > id[v])
            swap(u, v);
        addtoSegment(1, id[u], id[v], k);
        return;
    }
    if (dep[u] < dep[v])
        swap(u, v);
    addtoSegment(1, id[top[u]], id[u], k);
    addtoPath(par[top[u]], v, k);
}
int queryPath(int u, int v)
{
    if (top[u] == top[v])
    {
        if (id[u] > id[v])
            swap(u, v);
        return query(1, id[u], id[v]);
    }
    if (dep[u] < dep[v])
        swap(u, v);
    int ret = query(1, id[top[u]], id[u]) % mod;
    ret = (ret + queryPath(par[top[u]], v)) % mod;
    return ret;
}
inline void addtoSubtree(int root, int k)
{
    int r = id[root];
    addtoSegment(1, r, r + size[root] - 1, k);
}
inline int querySubtree(int root)
{
    int r = id[root];
    return query(1, r, r + size[root] - 1) % mod;
}
int main()
{
    std::ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n >> q >> rt >> mod;
    for (int i = 1; i <= n; i++)
        cin >> val[i];
    for (int i = 1; i < n; i++)
    {
        int x, y;
        cin >> x >> y;
        edge[x].push_back(y);
        edge[y].push_back(x);
    }
    dfs1(rt, 0, 1);
    dfs2(rt, rt);
    buildtree(1, 1, n);
//     cout<<'\n';
// for(int i=1;i<=n;i++)cout<<query(1,id[i],id[i])<<" \n"[i==n];
    while (q--)
    {
        int op, x, y, z;
        cin >> op;
        switch (op)
        {
        case 1:
            cin >> x >> y >> z;
            addtoPath(x, y, z);
            // for(int i=1;i<=n;i++)cout<<query(1,id[i],id[i])%mod<<" \n"[i==n];
            break;
        case 2:
            cin >> x >> y;
            cout << queryPath(x, y) << '\n';
            break;
        case 3:
            cin >> x >> z;
            addtoSubtree(x, z);
            // for(int i=1;i<=n;i++)cout<<query(1,id[i],id[i])%mod<<" \n"[i==n];
            break;
        case 4:
            cin >> x;
            cout << querySubtree(x) << '\n';
            break;
        
            
        }
    }
    return 0;
}

2024/4/10 19:20
加载中...