zoukankan      html  css  js  c++  java
  • codeforces396C

    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: 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: 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 ≤ n0 ≤ 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=0;
        bool f=0;
        char ch=' ';
        while(!isdigit(ch))
        {
            f|=(ch=='-'); ch=getchar();
        }
        while(isdigit(ch))
        {
            s=(s<<3)+(s<<1)+(ch^48); ch=getchar();
        }
        return (f)?(-s):(s);
    }
    #define R(x) x=read()
    inline void write(ll x)
    {
        if(x<0)
        {
            putchar('-'); x=-x;
        }
        if(x<10)
        {
            putchar(x+'0'); return;
        }
        write(x/10);
        putchar((x%10)+'0');
        return;
    }
    #define W(x) write(x),putchar(' ')
    #define Wl(x) write(x),putchar('
    ')
    const int N=300005,M=600005;
    const ll Mod=1000000007;
    int n,Q;
    inline void Ad(ll &x,ll y)
    {
        x+=y; x-=(x>=Mod)?Mod:0; x+=(x<0)?Mod:0;
    }
    namespace Tree
    {
        int tot=0,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=0,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]+1,dfs(to[i]);
            Out[x]=++cnt;
        }
        struct segment
        {
            ll S[N<<1];
            #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=0;
                while(x>0)
                {
                    Ad(ans,S[x]); x-=lowbit(x);
                }
                return ans;
            }
        }SGT[2];
        inline void Solve()
        {
            int i;
            Depth[1]=0; dfs(1);
            R(Q);
            while(Q--)
            {
                ll opt,rt,Val,Del;
                R(opt); R(rt);
                if(opt==1)
                {
                    Val=read()%Mod; R(Del);
                    SGT[0].Ins(In[rt],(Val+Del*Depth[rt]%Mod)%Mod);
                    SGT[0].Ins(Out[rt]+1,(-1)*(Val+Del*Depth[rt]%Mod)%Mod);
                    SGT[1].Ins(In[rt],Del);
                    SGT[1].Ins(Out[rt]+1,(-1)*Del);
                }
                else
                {
                    ll tmp,oo;
                    tmp=SGT[0].Que(In[rt]);
                    oo=SGT[1].Que(In[rt]);
                    Ad(tmp,(-1)*oo*Depth[rt]%Mod);
                    Wl(tmp);
                }
            }
        }
    }
    #define T Tree
    int main()
    {
        int i;
        R(n);
        for(i=2;i<=n;i++)
        {
            int x=read(); T::add(x,i);
        }
        T::Solve();
        return 0;
    }
    /*
    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
    */
    View Code
  • 相关阅读:
    性能测试实战
    毕业以后读书报告(不定时更新)
    sqlalchemy.orm.exc.flusherror:错误解决
    Anaconda安装第三方模块
    关于BeanShell报错提示Error invoking bsh method
    jmeter函数和变量
    jmeter插件安装及使用
    doc
    doc
    doc
  • 原文地址:https://www.cnblogs.com/gaojunonly1/p/11272764.html
Copyright © 2011-2022 走看看