Codeforces#232 C

6 篇文章 0 订阅
C. On Changing Tree
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

You are given a rooted tree consisting of n vertices numbered from 1 to n. The root of the tree is a vertex number 1.

Initially all vertices contain number 0. Then come q queries, each query has one of the two types:

  • The format of the query: 1 v x k. In response to the query, you need to add to the number at vertex v number x; to the numbers at the descendants of vertex v at distance 1, add x - k; and so on, to the numbers written in the descendants of vertex v at distancei, you need to add x - (i·k). The distance between two vertices is the number of edges in the shortest path between these vertices.
  • The format of the query: 2 v. In reply to the query you should print the number written in vertex v modulo 1000000007 (109 + 7).

Process the queries given in the input.

Input

The first line contains integer n (1 ≤ n ≤ 3·105) — the number of vertices in the tree. The second line contains n - 1 integers p2, p3, ...pn (1 ≤ pi < i), where pi is the number of the vertex that is the parent of vertex i in the tree.

The third line contains integer q (1 ≤ q ≤ 3·105) — the number of queries. Next q lines contain the queries, one per line. The first number in the line is type. It represents the type of the query. If type = 1, then next follow space-separated integers v, x, k (1 ≤ v ≤ n;0 ≤ x < 109 + 70 ≤ k < 109 + 7). If type = 2, then next follows integer v (1 ≤ v ≤ n) — the vertex where you need to find the value of the number.

Output

For each query of the second type print on a single line the number written in the vertex from the query. Print the number modulo1000000007 (109 + 7).


这场全是这样的题。。。吓死人。

首先用DFS把树拍平。。。然后看代码吧。。。看了就懂

#include<stdio.h>
#include<string.h>
#include<vector>
#include<iostream>

#define LL long long

using namespace std;

const bool Debug = 0;
const int MAXN = 310000;
const LL MOD = 1000000007LL;
LL sum[MAXN],sumk[MAXN];
int dep[MAXN],st[MAXN],ed[MAXN];
vector<int> chd[MAXN];
int tol,n;

inline int lowbit(int x){
	return x&-x;
}

inline LL Mod(LL x){
	return x % MOD;
}

void add(LL a[],int x,LL val){
	for(int i=x;i<=n;i+=lowbit(i))
		a[i] = Mod(a[i] + val);
	return ;
}

LL getVal(LL a[],int x){
	LL sum = 0;
	for(int i=x;i;i-=lowbit(i))
		sum = Mod(sum + a[i]);	
	return sum;
}

void Dfs(int now,int de){
	st[now] = tol++;
	dep[now] = de;
	int mm = chd[now].size();
	for(int i = 0;i < mm;i++)
		Dfs(chd[now][i],de+1);
	ed[now] = tol-1;
	return ;
}



int Work(){
	int i,l,r,typ,v,t,m;
	LL val,x,k;
	if (scanf("%d",&n) == EOF)
		return 0;
	memset(st,0,sizeof(st));
	memset(ed,0,sizeof(ed));
	memset(dep,0,sizeof(dep));
	memset(sum,0,sizeof(sum));
	memset(sumk,0,sizeof(sumk));
	for(i = 1;i <= n;i++)
		chd[i].clear();
	for(i = 2;i <= n;i++){
		cin >> t;
		chd[t].push_back(i);
	}
	tol = 1;
	Dfs(1,1);
	if (Debug) printf("hehe\n");
	if (Debug) {
		for (i = 1;i <= n;i++)
			printf("%d %d %d %d\n",i,dep[i],st[i],ed[i]);
	}
	cin >> m;
	for(i = 1;i <= m;i++){
		cin >> typ;
		if (typ == 1){
			cin >> v >> x >> k;
			//printf("xxoo\n");
			l = st[v];
			r = ed[v];
			val = Mod((LL)x + Mod(dep[v] * k));
			add(sum,l,val);
			//printf("xxoo\n");
			add(sum,r+1,-val);
			//printf("xxoo\n");
			add(sumk,l,k);
			//printf("xxoo\n");
			add(sumk,r+1,-k);
			//printf("xx4\n");
		}else{
			cin >> v;
			if (Debug) printf("xx1\n");
			LL ans = Mod(getVal(sum,st[v])+MOD);
			//printf("xo %lld %lld\n",getVal(sum,st[v]),getVal(sumk,st[v]));
			if (Debug) printf("xx3\n");
			ans = Mod(Mod(ans - Mod(dep[v] * Mod(getVal(sumk,st[v])))) + MOD);
			cout << ans << endl;
			if (Debug) printf("xx2\n");
		}
	}
	return 1;
}

int main(){
	while(Work());
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值