P7710 [Ynoi2077] stdmxeypz 题解

DFS 序分块,变成区间深度模 x 等于 y 的点加 z。散块暴力,考虑整块。

x 根号分治。xn 时,维护 Xi,j,k 表示 i 块被形如模 j 等于 k 的修改加了多少即可。

x>n 时维护 Yi,j 表示 i 块内深度为 j 的点被 x>n 的修改加了多少,

枚举此次操作影响到的深度 d,则需要对 Y[l,r],d 区间加 z,在第一维上差分即可。

空间复杂度 O(nn),调一调块长和阈值。

#include <cstdio>
#include <algorithm>
#define B 1500
#define K 450
using namespace std;
struct E
{
    int v, t;
} e[300050];
int n, m, c, z, L[350], R[350], a[300050], t[300050], b[300050], k[300050], d[300050], s[300050], h[300050], X[201][451][451], Y[300050][201];
void A(int u, int v)
{
    e[++c] = {v, h[u]};
    h[u] = c;
}
void D(int u)
{
    s[k[b[u] = ++z] = u] = 1;
    for (int i = h[u], v; i; i = e[i].t)
        d[v = e[i].v] = d[u] + 1, D(v), s[u] += s[v];
}
int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; ++i)
        t[i] = (i - 1) / B + 1;
    for (int i = 1; i <= t[n]; ++i)
        L[i] = (i - 1) * B + 1, R[i] = min(L[i] + B - 1, n);
    for (int i = 2, x; i <= n; ++i)
        scanf("%d", &x), A(x, i);
    D(1);
    for (int i = 0, o, v, x, y, z; i < m; ++i)
    {
        scanf("%d%d", &o, &v);
        if (o & 1)
        {
            scanf("%d%d%d", &x, &y, &z);
            int l = b[v], r = b[v] + s[v] - 1;
            if (t[l] == t[r])
            {
                for (int i = l; i <= r; ++i)
                    if ((d[k[i]] - d[v]) % x == y)
                        a[k[i]] += z;
                continue;
            }
            else
            {
                for (int i = l; i <= R[t[l]]; ++i)
                    if ((d[k[i]] - d[v]) % x == y)
                        a[k[i]] += z;
                for (int i = L[t[r]]; i <= r; ++i)
                    if ((d[k[i]] - d[v]) % x == y)
                        a[k[i]] += z;
                if (x <= K)
                    for (int i = t[l] + 1; i < t[r]; ++i)
                        X[i][x][(d[v] + y) % x] += z;
                else
                    for (int i = d[v] + y; i < n; i += x)
                        Y[i][t[l] + 1] += z, Y[i][t[r]] -= z;
            }
        }
        else
        {
            int q = a[v];
            for (int i = 1; i <= K; ++i)
                q += X[t[b[v]]][i][d[v] % i];
            for (int i = 1; i <= t[b[v]]; ++i)
                q += Y[d[v]][i];
            printf("%d\n", q);
        }
    }
    return 0;
}
posted @   Jijidawang  阅读(3)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示