luogu P7710 [Ynoi2077] stdmxeypz

https://www.luogu.com.cn/problem/P7710

相当于是这题丢到树上的版本
luogu P5309 [Ynoi2011] 初始化

不太会去掉log,
考虑一个修改i对一个询问j有几个限制,首先是时间 t i < t j t_i<t_j ti<tj这一维,
第二维是要满足 l i < l j < = r i l_i<l_j<=r_i li<lj<=ri
第三维是 d e p [ u j ] = d e p [ u i ] + y ( m o d    x ) dep[u_j]=dep[u_i]+y(\mod x) dep[uj]=dep[ui]+y(modx)

第三维按照上面那个套路搞个阈值分治即可

加几个卡常技巧即可
code:

#include<bits/stdc++.h>
#define N 600050
using namespace std;
inline int read() {
    register int x = 0;
    register char ch = getchar();
    for(; ch < '0' || ch > '9'; ) ch = getchar();
    for(; ch >= '0' && ch <= '9'; ) x = (x << 3) + (x << 1) + (ch - 48), ch = getchar();
    return x;
}
inline void PRT(register int x) {
    int s[20], top = 0;
    while(x) s[++ top] = x % 10, x /= 10;
    if(!top) s[++ top] = 0;
    while(top) putchar(s[top --] + '0');
    puts("");
}
struct edge {
    int v, nxt;
} e[N << 1];
int p[N], eid;
void init() {
    memset(p, -1, sizeof p);
    eid = 0;
}
inline void insert(int u, int v) {
    e[eid].v = v;
    e[eid].nxt = p[u];
    p[u] = eid ++;
}
int n, m, dfn, tot, gs, L[N], R[N], dep[N], s1[606][606], s2[N], blo, ans[N << 2];
int ss1[606][606], ss2[N], py[N], ss0[N];
void dfs(int u) {
    L[u] = ++ dfn;
    py[dfn] = u;
    for(int i = p[u]; i + 1; i = e[i].nxt) {
        int v = e[i].v;
        dep[v] = dep[u] + 1;
        dfs(v);
    }
    R[u] = dfn;
}
inline void update(int x, register int y, int o) {
    if(x <= blo) s1[x][y] += o;
    else for(; y <= n; y += x) s2[y] += o;
}
inline int query(int x) {
    int ret = s2[x];
    for(register int i = 1; i <= blo; i ++) ret += s1[i][x % i];
    return ret;
}
inline void clear(int x, register int y) {
    if(x <= blo) s1[x][y] = 0;
    else for(; y <= n; y += x) s2[y] = 0;
}
struct Q {
    int l, x, y, o, id;
} q[N << 2], ls[N << 2];
void cdq(int l, int r) {
    if(l == r) return ;
    int mid = (l + r) >> 1;
    cdq(l, mid), cdq(mid + 1, r);
    int i = l, j = mid + 1, k = l - 1;
    while(i <= mid && j <= r) {
        if(q[i].l <= q[j].l) {
            if(!q[i].id) update(q[i].x, q[i].y, q[i].o);
            ls[++ k] = q[i ++];
        } else {
            if(q[j].id) ans[q[j].id] += query(q[j].x);
            ls[++ k] = q[j ++];
        }
    }
    while(j <= r) {
        if(q[j].id) ans[q[j].id] += query(q[j].x);
        ls[++ k] = q[j ++];
    }
    for(int w = l; w < i; w ++) if(!q[w].id) clear(q[w].x, q[w].y);
    while(i <= mid) {
        ls[++ k] = q[i ++];
    }
    for(int i = l; i <= r; i ++) q[i] = ls[i];
}
int main() {
    init();
    n = read(), m = read();
    for(int i = 2; i <= n; i ++) {
        int x;
        x = read();
        insert(x, i);
    }
    blo = sqrt(n);
    dfs(1);
    //for(int i = 1; i <= n; i ++) printf("%d ", dep[i]); printf("\n");
    for(int i = 1; i <= m; i ++) {
        int o, u, x, y, op;
        op = read(), u = read();
        if(op == 2) {
            q[++ tot] = (Q){L[u], dep[u], 0, 0, ++ gs};
            ans[gs] += ss0[u] + ss2[dep[u]];
            for(int j = 1; j <= blo; j ++)
                ans[gs] += ss1[j][dep[u] % j];//, printf("*%d*", ss1[j][dep[u] % j]);
        }
        else {
            x = read(), y = read(), o = read();
            y = (y + dep[u]) % x;
            q[++ tot] = (Q){L[u], x, y, o, 0};
            if(L[u] <= blo) {
                tot --;
                if(x <= blo) ss1[x][y] += o;
                else for(int j = y; j <= n; j += x) ss2[j] += o;
                
                for(int j = 1; j < L[u]; j ++) {
                    int v = py[j];
                    if(dep[v] % x == y) ss0[v] -= o;
                }
            }
            q[++ tot] = (Q){R[u] + 1, x, y, -o, 0};
            if(R[u] + blo >= n) {
                tot --;
                for(int j = R[u] + 1; j <= n; j ++) {
                    int v = py[j];
                    if(dep[v] % x == y) ss0[v] -= o;
                }
            }
        }
    }
    cdq(1, tot);
    for(int i = 1; i <= gs; i ++) PRT(ans[i]);
    return 0;
}

posted @ 2021-09-01 21:48  lahlah  阅读(46)  评论(0编辑  收藏  举报