codeforces396C
On Changing Tree
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 vat distance 1, add x - k; and so on, to the numbers written in the descendants of vertex v at distance i, 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 qlines 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 + 7; 0 ≤ 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 modulo 1000000007 (109 + 7).
Examples
3
1 1
3
1 1 2 1
2 1
2 2
2
1
Note
You can read about a rooted tree here: http://en.wikipedia.org/wiki/Tree_(graph_theory).
给出一棵以1为根的树,形式是从节点2开始给出每个节点的父亲节点;
然后是m次操作,操作分为两种,1 v, x, k,表示在以v为根的子树上添加,
添加的法则是看这个节点与v节点的距离为i的话,加上x-i*k;2 v查询节点v的值。
sol:子树操作显然可以搞出dfs序然后修改一段区间,然后修改是一个经典操作,看做是子树每个节点加上x+deg[v]*k,查询y的时候减去dep[y]*k即可
/*
给出一棵以1为根的树,形式是从节点2开始给出每个节点的父亲节点;
然后是m次操作,操作分为两种,1 v, x, k,表示在以v为根的子树上添加,
添加的法则是看这个节点与v节点的距离为i的话,加上x-i*k;2 v查询节点v的值。
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline ll read()
{
ll s=;
bool f=;
char ch=' ';
while(!isdigit(ch))
{
f|=(ch=='-'); ch=getchar();
}
while(isdigit(ch))
{
s=(s<<)+(s<<)+(ch^); ch=getchar();
}
return (f)?(-s):(s);
}
#define R(x) x=read()
inline void write(ll x)
{
if(x<)
{
putchar('-'); x=-x;
}
if(x<)
{
putchar(x+''); return;
}
write(x/);
putchar((x%)+'');
return;
}
#define W(x) write(x),putchar(' ')
#define Wl(x) write(x),putchar('\n')
const int N=,M=;
const ll Mod=;
int n,Q;
inline void Ad(ll &x,ll y)
{
x+=y; x-=(x>=Mod)?Mod:; x+=(x<)?Mod:;
}
namespace Tree
{
int tot=,Next[M],to[M],head[N];
inline void add(int x,int y)
{
Next[++tot]=head[x];
to[tot]=y;
head[x]=tot;
}
int In[N],Out[N],cnt=,Depth[N];
inline void dfs(int x)
{
int i;
In[x]=++cnt;
for(i=head[x];i;i=Next[i]) Depth[to[i]]=Depth[x]+,dfs(to[i]);
Out[x]=++cnt;
}
struct segment
{
ll S[N<<];
#define lowbit(x) ((x)&(-x))
inline void Ins(int x,int Val)
{
while(x<=cnt)
{
Ad(S[x],Val); x+=lowbit(x);
}
}
inline int Que(int x)
{
ll ans=;
while(x>)
{
Ad(ans,S[x]); x-=lowbit(x);
}
return ans;
}
}SGT[];
inline void Solve()
{
int i;
Depth[]=; dfs();
R(Q);
while(Q--)
{
ll opt,rt,Val,Del;
R(opt); R(rt);
if(opt==)
{
Val=read()%Mod; R(Del);
SGT[].Ins(In[rt],(Val+Del*Depth[rt]%Mod)%Mod);
SGT[].Ins(Out[rt]+,(-)*(Val+Del*Depth[rt]%Mod)%Mod);
SGT[].Ins(In[rt],Del);
SGT[].Ins(Out[rt]+,(-)*Del);
}
else
{
ll tmp,oo;
tmp=SGT[].Que(In[rt]);
oo=SGT[].Que(In[rt]);
Ad(tmp,(-)*oo*Depth[rt]%Mod);
Wl(tmp);
}
}
}
}
#define T Tree
int main()
{
int i;
R(n);
for(i=;i<=n;i++)
{
int x=read(); T::add(x,i);
}
T::Solve();
return ;
}
/*
Input
3
1 1
3
1 1 2 1
2 1
2 2
Output
2
1 Input
10
1 2 3 4 4 3 3 6 7
10
1 6 13 98
1 7 17 66
1 5 32 39
1 1 9 5
1 7 27 11
1 1 24 79
1 5 87 86
2 2
1 5 9 38
2 5
Output
999999956
999999832
*/
codeforces396C的更多相关文章
随机推荐
- 解决:error LNK1169: 找到一个或多个多重定义的符号
每一个c++项目中可以包含多个cpp文件和.h文件,不过只能有而且必须有一个cpp文件中包含main函数,否则就会报错.所以在一个c++项目中不能单独运行一个cpp文件,只能运行一个项目.如果你想一个 ...
- element 右键菜单
右键菜单 这是一个右键菜单的组件 <template> <div id="dropMenu" :style="style" style=&qu ...
- kvm第四章-- 虚拟化网络管理
- 【转载】Sqlserver使用SUBSTRING函数截取字符串
在SQL语句查询过程中,Sqlserver支持使用LEFT().RIGHT().SUBSTRING()等几个函数对字符串进行截取操作,SubString函数相对于其他两个函数来说更灵活,使用场景更多, ...
- JS 客户端(浏览器)存储数据之 localStorage、sessionStorage和indexDB
基本概念 1.localStorage和sessionStorage是HTML5 Web存储的提供的两种存储方式,在IE7以上以及大多数浏览器都是支持的 2.localStorage和sessionS ...
- iOS音频学习笔记三:音频会话管理
使用Audio Session API ,可以指定App需要的音频行为,比如,当播放音频时,使得其他应用App静音或者混和在一起,也可以指定当App的音频被中断(例如被电话)时的行为,还 ...
- 从客户发送http请求到服务器返回http之间发生了什么
由于我知识有限,可能会有模糊或者错误的地方,欢迎讨论与指正. 1.浏览器发出http请求 当用户访问一个url时,浏览器便会开始生成一个http请求. 首先获取http请求中所需要的参数,如url,c ...
- djangoNotes
学员管理 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF- ...
- Oracle 定时JOB
讲一下Oracle创建临时job小窍门,创建Oracle临时JOB是为了临时执行调用过程或者函数,只调用一次. 1.创建Oracle临时job declare VJOB number; begin ...
- kali 系统膨胀后如何处理
1.一般使用的kali 安装都是将系统文件全部放在一个总分区中,应用程序会产生临时文件,另外在安装软件的时候会出现 系统框架的不同,但是kali并不会检测该问题,直接当依赖的框架下载,可以是使用命令 ...