There is a rooted tree with n nodes, number from 1-n. Root’s number is 1.Each node has a value ai.

Initially all the node’s value is 0.

We have q operations. There are two kinds of operations.

1 v x k : a[v]+=x , a[v’]+=x-k (v’ is child of v) , a[v’’]+=x-2*k (v’’ is child of v’) and so on.

2 v : Output a[v] mod 1000000007(10^9 + 7).

Input

First line contains an integer T (1 ≤ T ≤ 3), represents there are T test cases.

In each test case:

The first line contains a number n.

The second line contains n-1 number, p2,p3,…,pn . pi is the father of i.

The third line contains a number q.

Next q lines, each line contains an operation. (“1 v x k” or “2 v”)

1 ≤ n ≤ 3*10^5

1 ≤ pi < i

1 ≤ q ≤ 3*10^5

1 ≤ v ≤ n; 0 ≤ x < 10^9 + 7; 0 ≤ k < 10^9 + 7

Output

For each operation 2, outputs the answer.

Sample Input

1 3 1 1 3 1 1 2 1 2 1 2 2

Sample Output

2 1
 
更新v的时候,他的子孙的值就是这个 x+d[v]*k-d[s]*k
一个树状数组维护x+d[v]*k
一个维护sigma(k)

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=3e5+;
const LL mod=1e9+;
int l[N],r[N];
LL dep[N],A[N],B[N];
int tot,head[N],n,t;
struct node{
   int next,to;
}e[N];
void add(int u,int v){
   e[tot].next=head[u];
   e[tot].to=v;
   head[u]=tot++;
}
void addA(int pos,LL val){
    for(;pos<=n+;pos+=pos&(-pos))
        A[pos]=(A[pos]+val)%mod;
}
void addB(int pos,LL val){
    for(;pos<=n+;pos+=pos&(-pos))
        B[pos]=(B[pos]+val)%mod;
}
void dfs(int x){
   l[x]=t++;
   for(int i=head[x];i+;i=e[i].next){
    dep[e[i].to]=dep[x]+;dfs(e[i].to);
   }
   r[x]=t;
}
LL sum(int pos,int pp){
    LL ret=,ans=;
    for(int i=pos;i;i-=i&(-i))
        ret=(ret+A[i])%mod;
    for(int i=pos;i;i-=i&(-i))
        ans=(ans+B[i])%mod;
    ans=((LL)ans*dep[pp])%mod;
    return (ret-ans+*mod)%mod;
}
int main(){
     int m,T,x,k,v,op;
     for(scanf("%d",&T);T--;){
        scanf("%d",&n);
        for(int i=;i<=n;++i) head[i]=-;
        for(int i=;i<=n+;++i) A[i]=B[i]=;
        tot=,dep[]=t=;
        for(int i=;i<=n;++i)
        {
            scanf("%d",&x);add(x,i);
        }
        dfs();
        scanf("%d",&m);
        while(m--){
            scanf("%d%d",&op,&v);
            if(op==){
                scanf("%d%d",&x,&k);
                LL ct=(x+dep[v]*k)%mod;
                addA(l[v],ct);
                addA(r[v],-ct);
                addB(l[v],k);
                addB(r[v],-k);
            }
            else printf("%I64d\n",sum(l[v],v));
        }
     }
}
 
PSHTTR: Pishty 和城堡
题目描述 Pishty 是生活在胡斯特市的一个小男孩。胡斯特是胡克兰境内的一个古城,以其中世纪风格 的古堡和非常聪明的熊闻名全国。 胡斯特的镇城之宝是就是这么一座古堡,历史上胡斯特依靠这座古堡抵挡住了疯人国的大军。 对于 Pishty 来说,真正吸引他的是古堡悠长的走廊和高耸的钟楼,以及深藏于其中的秘密…… 古堡可以用一棵 N 个节点的树的描述,树中有 N −1 条无向边,每条边有一个魔法数字 C。 当一个旅游团参观古堡时,他们会选择树上 U 到 V 的路径游览。他们认为,如果一条边的魔 法数字不超过 K,那么这条边是有趣的。而一条路径的吸引力就是路径上所有有趣的边的魔法数 字的异或和。 胡克兰的国王希望大力发展旅游业,因此他下令求出所有旅游团的游览路径的吸引力。而 Pishty立志成为国王身边的骑士,便自告奋勇承担了这一任务。但旅游团实在太多了,他也算不过 来。所以,请你帮Pishty解决这一问题:给定 M 个旅游团的旅游路径,请你求出路径的吸引力。
输入格式
输入的第一行包含一个整数 T,代表测试数据的组数。接下来是 T 组数据。 每组数据的第一行包含一个整数 N,代表树的节点个数。 接下来 N −1 行,每行描述一条边。每行包含三个整数 U,V,C,代表节点 U 和 V 之间连有 一条魔法数字为 C 的边。 接下来一行包含一个整数 M,代表旅游团的数量。 接下来 M 行,每行包含三个整数 U,V,K,描述一个旅游团。
输出格式
对于每个旅游团,输出一行,包含一个整数,代表其路径的吸引力。
数据范围和子任务 • 1 ≤ T ≤ 5 • 1 ≤ N,M ≤ 105
• 1 ≤ U,V ≤ N • 1 ≤ C,K ≤ 109
子任务 1(10 分): • 1 ≤ N,M ≤ 10
子任务 2(20 分): • 1 ≤ N,M ≤ 103
子任务 3(70 分): • 无附加限制
样例数据
输入
1
5
1 2 1
2 3 2
2 4 5
3 5 10
6
5 4 5
5 4 10
5 4 1
1 2 1
4 1 10
1 5 8
输出
7
13
0
1
4
3
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+;
int L[N],R[N],dep[N],tot,t,head[N],fa[N],ans[N];
struct et{
   int v,next;
}e1[N<<];
struct node{
   int u,v,w,id;
   bool operator <(const node &A)const{
   return w<A.w;
   }
}sor[N],e2[N];
struct tct{
   int l,r,w;
}tr[N<<];
void add(int u,int v){
   e1[tot].v=v;e1[tot].next=head[u];head[u]=tot++;
   e1[tot].v=u;e1[tot].next=head[v];head[v]=tot++;
}
void push_down(int rt){
    if(tr[rt].l==tr[rt].r) return;
   if(tr[rt].w){
    tr[rt<<].w^=tr[rt].w;tr[rt<<|].w^=tr[rt].w;
    tr[rt].w=;
   }
}
void build(int l,int r,int rt){
   tr[rt].l=l,tr[rt].r=r,tr[rt].w=;
   if(l==r) return;
   int mid=(l+r)>>;
   build(l,mid,rt<<);
   build(mid+,r,rt<<|);
}
void dfs(int u){
    L[u]=t++;
   for(int i=head[u];i+;i=e1[i].next){
    int v=e1[i].v;
    if(v==fa[u]) continue;
    dep[v]=dep[u]+;
    fa[v]=u;
    dfs(v);
   }
   R[u]=t;
}
void add(int L,int R,int rt,int val){
   int l=tr[rt].l,r=tr[rt].r;
   if(l==L&&R==r) {
    tr[rt].w^=val;
    return;
   }
   push_down(rt);
   int mid=(l+r)>>;
   if(R<=mid) add(L,R,rt<<,val);
   else if(L>mid) add(L,R,rt<<|,val);
   else {
    add(L,mid,rt<<,val);
    add(mid+,R,rt<<|,val);
   }
}
int query(int pc,int rt){
    int l=tr[rt].l,r=tr[rt].r;
    if(l==r) return tr[rt].w;
    int mid=(l+r)>>;
    push_down(rt);
    if(pc<=mid) return query(pc,rt<<);
    else return query(pc,rt<<|);
}
int main(){
    int T,n,m,u,v,w;
    for(scanf("%d",&T);T--;){
        scanf("%d",&n);
        build(,n,);
        memset(head,-,sizeof(head));
        tot=;
        t=;
        for(int i=;i<n;++i) {
            scanf("%d%d%d",&u,&v,&w);
            add(u,v);
            sor[i].u=u,sor[i].v=v,sor[i].w=w;
        }
        dfs();
        scanf("%d",&m);
        for(int i=;i<=m;++i){
            scanf("%d%d%d",&e2[i].u,&e2[i].v,&e2[i].w);
            e2[i].id=i;
        }
        sort(sor+,sor+n);
        sort(e2+,e2+m+);
        int ii=;
        for(int i=;i<=m;++i){
            while(sor[ii].w<=e2[i].w&&ii<n) {
                int u=sor[ii].u,v=sor[ii].v;
                if(dep[u]<dep[v]) swap(u,v);
                add(L[u],R[u]-,,sor[ii].w);
                ++ii;
            }
            int t1=query(L[e2[i].u],),t2=query(L[e2[i].v],);
            ans[e2[i].id]=t1^t2;
        }
        for(int i=;i<=m;++i) printf("%d\n",ans[i]);
    }
}
 
 
 
 
 
 
 
 
 
 

DFS序--一般都要转化为顶点到每个点的更多相关文章

  1. 2016 ACM/ICPC Asia Regional Dalian Online 1010 Weak Pair dfs序+分块

    Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Submissio ...

  2. BZOJ_2434_[NOI2011]_阿狸的打字机_(AC自动机+dfs序+树状数组)

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=2434 给出\(n\)个字符串,\(m\)个询问,对于第\(i\)个询问,求第\(x_i\)个字 ...

  3. BZOJ2434[Noi2011]阿狸的打字机——AC自动机+dfs序+树状数组

    题目描述 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的: l 输入小 ...

  4. USACO10FEB]慢下来Slowing down dfs序 线段树

    [USACO10FEB]慢下来Slowing down 题面 洛谷P2982 本来想写树剖来着 暴力数据结构直接模拟,每头牛回到自己的农场后,其子树下的所有牛回到农舍时,必定会经过此牛舍,即:每头牛回 ...

  5. [bzoj4009] [HNOI2015]接水果 整体二分+扫描线+dfs序+树状数组

    Description 风见幽香非常喜欢玩一个叫做 osu!的游戏,其中她最喜欢玩的模式就是接水果. 由于她已经DT FC 了The big black, 她觉得这个游戏太简单了,于是发明了一个更 加 ...

  6. 【BZOJ-3779】重组病毒 LinkCutTree + 线段树 + DFS序

    3779: 重组病毒 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 224  Solved: 95[Submit][Status][Discuss] ...

  7. 【BZOJ-3881】Divljak AC自动机fail树 + 树链剖分+ 树状数组 + DFS序

    3881: [Coci2015]Divljak Time Limit: 20 Sec  Memory Limit: 768 MBSubmit: 508  Solved: 158[Submit][Sta ...

  8. DFS序详解

    dfs序就是一棵树在dfs遍历时组成的节点序列. 它有这样一个特点:一棵子树的dfs序是一个区间. 下面是dfs序的基本代码: void dfs(int x,int pre,int d){//L,R表 ...

  9. [BZOJ 2819]NIM(dfs序维护树上xor值)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2819 分析: 树上的nim游戏,关键就是要判断树上的一条链的异或值是否为0 这个题目有 ...

随机推荐

  1. 计算3的n次幂htm代码

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. Galera将死——MySQL Group Replication正式发布

    2016-12-14 来源:InsideMySQL 作者:姜承尧 MySQL Group Replication GA 很多同学表示昨天的从你的全世界路过画风不对,好在今天MySQL界终于有大事情发生 ...

  3. 与IBM的Lin Sun关于Istio 1.0和微服务的问答

    北京时间 7 月 31 日,Istio 正式发布了 1.0 版本,并表示已经可用于生产环境.该版本的主要新特性包括跨集群 mesh 支持.细粒度流量控制以及在一个 mesh 中增量推出 mutual ...

  4. Coursera课程笔记----C程序设计进阶----Week 3

    函数的递归(Week 3) 什么是递归 引入 函数可以嵌套调用:无论嵌套多少层,原理都一样 函数不能嵌套定义:不能在一个函数里再定义另一个函数,因为所有函数一律平等 问题:一个函数能调用它自己吗? 举 ...

  5. 用PHP获取网页上的信息相对于xpath效率低点

    用php实现对网页的抓取,及信息的收集,其实就是爬数据,具体实现步骤如下,首先应引入两个文件curl_html_get.php和save_file.php文件,两个文件具体代码是这样的curl_htm ...

  6. 一、Spring的控制反转(IOC)学习

    一.控制反转 1.什么是控制反转? 控制反转(Inversion of Control,缩写为IoC),是面向对象中的一种设计原则,可以用来减低计算机代码之间的耦合度.其中最常见的方式叫做依赖注入(D ...

  7. STM32 标准库V3.5启动文件startup_stm32f10xxx.s分析

    layout: post tags: [STM32] comments: true 文章目录 layout: post tags: [STM32] comments: true 前言 分析startu ...

  8. python是如何进行参数传递的?

    在分析python的参数传递是如何进行的之前,我们需要先来了解一下,python变量和赋值的基本原理,这样有助于我们更好的理解参数传递. python变量以及赋值 数值 从几行代码开始 In [1]: ...

  9. iOS开发--性能调优记录

    CPU VS GPU 关于绘图和动画有两种处理的方式:CPU(中央处理器)和GPU(图形处理器).但是由于历史原因,我们可以说CPU所做的工作都在软件层面,而GPU在硬件层面 对于图像处理,通常用硬件 ...

  10. 0804_serial port

    其实这个程序总的来说是有问题的 仿真图: MacroAndConst.h #ifndef _MACRO_AND_CONST_H_ #define _MACRO_AND_CONST_H_ typedef ...