On Changing Tree

CodeForces - 396C

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

Input
3
1 1
3
1 1 2 1
2 1
2 2
Output
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的更多相关文章

随机推荐

  1. 多线程使用libcurl

    curl默认情况下有两个地方是线程不安全的, 需要特殊处理, 1是curl_global_init 这个函数必须单线程调用, 2是默认多线程调用https会莫名其妙的挂掉, 以下是网上的解决方案 ht ...

  2. 用 Scoop 管理你的 Windows 软件

    包管理系统,Homebrew 就是 macOS 上体验最佳的软件包管理,能帮助我们方便快捷.干净利落的管理软件.在Windows平台上也有一个非常棒的包管理软件--Scoop.Scoop 最适合安装那 ...

  3. 一行命令开启VNC 和windows之间复制粘贴功能

    sudo apt install autocutsel 安装完成之后: [注意]中文会乱码!!! 执行以下命令: autocutsel 这个则是后台运行,选择一种即可: autocutsel -f

  4. DNS服务——搭建企业内网DNS服务器的作用

    前言 DNS服务——服务端 和 客户端 配置 介绍了如何在DNS安装DNS服务,更改一下配置文件就可以依据根提示解析全球域名.既然使用互联网上的DNS服务器就可以解析全球域名,为何还要自掏腰包搭建DN ...

  5. Windows——Thinkpad 开机显示pwmtr64v.dll找不到指定的模块

    解决方法:进入设备管理器,展开系统设备分页,找到Lenovo Power Manager ,右键,更新驱动程序,浏览计算机上的驱动程序, 让我从计算机上的可用驱动程序列表中选取,选择Lenovo Po ...

  6. G1垃圾收集器堆内存划分与角色分派【纯理论】

    接着上一次[https://www.cnblogs.com/webor2006/p/11123522.html]G1学习继续开启理论之旅.. G1的设计规划是要替换掉CMS[理想化的] G1在某些方面 ...

  7. k8s的高可用

    一.高可用原理   配置一台新的master节点,然后在每台node节点上安装nginx,nginx通过内部的负载均衡将node节点上需要通过访问master,kube-apiserver组件的请求, ...

  8. P2458 [SDOI2006]保安站岗[树形dp]

    题目描述 五一来临,某地下超市为了便于疏通和指挥密集的人员和车辆,以免造成超市内的混乱和拥挤,准备临时从外单位调用部分保安来维持交通秩序. 已知整个地下超市的所有通道呈一棵树的形状:某些通道之间可以互 ...

  9. web上常见的攻击方式及简单的防御方法

    SQL注入最常见的攻击方式,所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令,比如先前的很多影视网站泄露VIP会员密码大 ...

  10. latex 表格每行设置不同字体

    Each cell of a table is set in a box, so that a change of font style (or whatever) only lasts to the ...