70求助!
查看原帖
70求助!
433966
_Agony楼主2021/9/2 19:57

#2#9#10莫名TLE

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;
const int N = 2e6 + 5;

int n, m, s;
int num;
int cnt, mod;
int a[N], b[N], fa[N];//b是原数据, a是dfs序数据 
int idx[N], top[N];//idx是x的dfs序 
int son[N], tot[N];//重儿子, 重量 
int deep[N], head[N];

struct bal {
    int nxt;
    int to;
};
bal e[N<<1];

struct ball {
    int l, r;
    int sum;
    int size;
    int lazy;
};
ball t[N<<2];

int re() {
    int x = 0, f = 1;
    char ch = getchar();
    while (ch < '0'||ch > '9') {
        if(ch == '-') f = -1;
        ch = getchar();
    }
    while (ch <= '9'&&ch >= '0') {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}

void add(int u, int v) {
    ++cnt;
    e[cnt].nxt = head[u];
    e[cnt].to = v;
    head[u] = cnt;
}

int dfs1(int x, int f, int dep) {//预处理 
    deep[x] = dep;
    tot[x] = 1; fa[x] = f;
    int maxson = -1;
    for(int i = head[x]; i; i = e[i].nxt) {
        int v = e[i].to;
        if(v == f) continue;
        tot[x] += dfs1(v, x, dep + 1);//回溯求重量 
        maxson = max(maxson, tot[v]);//维护x的重儿子 
    }
    son[x] = maxson;
    return tot[x];
}

void dfs2(int x, int ftop) {//找top 
    idx[x] = ++num;
    a[num] = b[x];
    top[x] = ftop;
    if(!son[x]) return;//到底了就返回 
    for(int i = head[x]; i; i = e[i].nxt) {
        int v = e[i].to;
        if(!idx[v]) dfs2(v, v);
    }
}

void update(int k) {
    t[k].sum = (t[k<<1].sum + t[k<<1|1].sum + mod) % mod;
}

void pushdown(int k) {
    if(!t[k].lazy) return ;
    t[k<<1].sum += (t[k<<1].size * t[k].lazy + mod) % mod;
    t[k<<1|1].sum += (t[k<<1|1].size * t[k].lazy + mod) % mod;
    t[k<<1].lazy += t[k].lazy;
    t[k<<1|1].lazy += t[k].lazy;
    t[k].lazy = 0;
}

void build(int p, int l, int r) {
    if(l < 0||r > n) return ;
    t[p].l = l; t[p].r = r;
    t[p].size = (r - l) + 1;
    if(l == r) {
        t[p].sum = a[l];
        return ;
    }
    int mid = (l + r) / 2;
    build(p * 2, l, mid);
    build(p * 2 + 1, mid + 1, r);
    update(p);
}

void Interval_addition(int p, int l, int r, int val) {//路径加 
    if(l <= t[p].l&&r >= t[p].r) {
        t[p].sum += (t[p].size * val + mod) % mod;
        t[p].lazy += val;
        return ;
    }
    pushdown(p);
    int mid = (t[p].l + t[p].r) >> 1;
    if(l <= mid) Interval_addition(p<<1, l, r, val);
    if(r > mid) Interval_addition(p<<1|1, l, r, val);
    update(p);
}

int Interval_summation(int p, int l, int r) {//路径求和 
    if(t[p].l >= l&&t[p].r <= r) {
        return t[p].sum;
    }
    int mid = (t[p].l + t[p].r)>>1;
    pushdown(p);   int ans = 0;
    if(l <= mid) ans = (ans + Interval_summation(p<<1, l, r) + mod) % mod;
    if(r > mid) ans = (ans + Interval_summation(p<<1|1, l, r) + mod) % mod;
    return ans;
}

void Tree_addition(int x, int y, int val) {//子树加 
    while (top[x] != top[y]) {
        if(deep[top[x]] < deep[top[y]]) swap(x, y);
        Interval_addition(1, idx[top[x]], idx[x], val);
        x = fa[top[x]];
    }
    if(deep[x] < deep[y]) swap(x ,y);
    Interval_addition(1, idx[y], idx[x], val);
}

void Tree_summation(int x, int y) {//子树求和 
    int ans = 0;
    while (top[x] != top[y]) {
        if(deep[top[x]] < deep[top[y]]) swap(x, y);
        ans = (ans + Interval_summation(1, idx[top[x]], idx[x])) % mod;
        x = fa[top[x]];
    }
    if(deep[x] < deep[y]) swap(x, y);
    ans = (ans + Interval_summation(1, idx[y], idx[x])) % mod;
    printf("%d\n", ans);
}

int main() {
    int xi, yi, op;
    int x, y, z;
    n = re(); m = re();
    s = re(); mod = re();
    for(int i = 1; i <= n; i++) 
        b[i] = re();
    for(int i = 1; i < n; i++) {
        xi = re(); yi = re();
        add(xi, yi); add(yi, xi);
    }
    dfs1(s, 0, 1);
    dfs2(s, s);
    build(1, 1, n);
    while (m--) {
            op = re();
        if(op == 1) {
            x = re(); y = re(); z = re();
            Tree_addition(x, y, z);
        }
        else if(op == 2) {
            x = re(); y = re();
            Tree_summation(x, y);
        }
        else if(op == 3) {
            x = re(); z = re();
            Interval_addition(1, idx[x], idx[x] + tot[x] - 1, z % mod);
        }
        else if(op == 4) {
            x = re();
            cout << Interval_summation(1, idx[x], idx[x] + tot[x] - 1) << endl;
        }
    }
    return 0;
}
2021/9/2 19:57
加载中...