版权声明:希望能在自己成长的道路上帮到更多的人,欢迎各位评论交流 https://blog.csdn.net/yiqzq/article/details/81880599
原题地址:http://acm.fzu.edu.cn/problem.php?pid=2277
题意:给定一棵根为1, n个结点的树. 有q个操作,有两种不同的操作
思路: 先 遍历, 得到这棵树的 序列, 并且记录每个结点的子孙(包括自己)的起始和结束位置, 以及每个结点的深度. 则对于1操作: 的每个子孙结点的变化情况为 其中 对所有结点贡献相同,而 k对每个结点的贡献度取决于结点i的深度. 所以可以用线段树, 对于每次操作一,所有v的子孙结点都加上 然后对于 每次记录 , 到最后更新的时候再乘以结点的深度即可.
#include <cmath>
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector>
#include <stack>
#include <set>
#include <map>
#include <cctype>
#define eps 1e-8
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define CLR(x,y) memset((x),y,sizeof(x))
#define fuck(x) cerr << #x << "=" << x << endl
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int seed = 131;
const int maxn = 3e5 + 5;
const int mod = 1e9 + 7;
int n;
struct node {
int v, nxt;
} e[maxn];
int tot, head[maxn];
int st[maxn], en[maxn], cnt, dep[maxn];
inline int read() {//读入挂
int ret = 0, c, f = 1;
for (c = getchar(); !(isdigit(c) || c == '-'); c = getchar());
if (c == '-') f = -1, c = getchar();
for (; isdigit(c); c = getchar()) ret = ret * 10 + c - '0';
if (f < 0) ret = -ret;
return ret;
}
void init_head() {
tot = 0;
cnt = 0;
for (int i = 0; i <= n; i++) head[i] = -1;
}
inline void add_edge(int u, int v) {
e[tot].v = v;
e[tot].nxt = head[u];
head[u] = tot++;
}
void dfs(int u, int d) {
dep[cnt] = d;
st[u] = cnt++;
for (int i = head[u]; ~i; i = e[i].nxt) {
int v = e[i].v;
dfs(v, d + 1);
}
en[u] = cnt;
}
ll xx[maxn << 2], kk[maxn << 2];
void push_down(int rt) {
xx[rt << 1] += xx[rt];
xx[rt << 1 | 1] += xx[rt];
kk[rt << 1] += kk[rt];
kk[rt << 1 | 1] += kk[rt];
// 这边的取模去掉几乎快1倍的速度
// xx[rt << 1] %= mod;
// xx[rt << 1 | 1] %= mod;
// kk[rt << 1] %= mod;
// kk[rt << 1 | 1] %= mod;
xx[rt] = 0;
kk[rt] = 0;
}
void build(int l, int r, int rt) {
xx[rt] = kk[rt] = 0;
if (l == r) return;
int mid = (l + r) >> 1;
build(lson);
build(rson);
}
void updata(int L, int R, ll x, ll k, int l, int r, int rt) {
if (L <= l && R >= r) {
// xx[rt] = (xx[rt] + x + mod) % mod;
xx[rt] = xx[rt] + x ;
// kk[rt] = (kk[rt] + k + mod) % mod;
kk[rt] = kk[rt] + k;
return;
}
push_down(rt);
int mid = (l + r) >> 1;
if (mid >= L) updata(L, R, x, k, lson);
if (mid < R) updata(L, R, x, k, rson);
}
ll query(int p, int l, int r, int rt) {
if (l == r) {
return xx[rt] + dep[l] * kk[rt];
// return ans % mod;
}
push_down(rt);
int mid = (l + r) >> 1;
if (mid >= p) return query(p, lson);
else return query(p, rson);
}
int main() {
int t, q;
t = read();
while (t--) {
n = read();
init_head();
for (int i = 2; i <= n; i++) {
int x;
x = read();
add_edge(x, i);
}
dfs(1, 1);
build(0, cnt - 1, 1);
q = read();
while (q--) {
int op, x, v, k;
op = read();
if (op == 2) {
x = read();
ll ans = query(st[x], 0, cnt - 1, 1);
ans = (ans % mod + mod) % mod;
printf("%I64d\n", ans);
} else {
v = read();
x = read();
k = read();
updata(st[v], en[v] - 1, x + 1LL * dep[st[v]]*k, -k, 0, cnt - 1, 1);
}
}
}
return 0;
}