• DFS序--一般都要转化为顶点到每个点


    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+88;
    const LL mod=1e9+7;
    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+8;pos+=pos&(-pos))
            A[pos]=(A[pos]+val)%mod;
    }
    void addB(int pos,LL val){
        for(;pos<=n+8;pos+=pos&(-pos))
            B[pos]=(B[pos]+val)%mod;
    }
    void dfs(int x){
       l[x]=t++;
       for(int i=head[x];i+1;i=e[i].next){
        dep[e[i].to]=dep[x]+1;dfs(e[i].to);
       }
       r[x]=t;
    }
    LL sum(int pos,int pp){
        LL ret=0,ans=0;
        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+2*mod)%mod;
    }
    int main(){
         int m,T,x,k,v,op;
         for(scanf("%d",&T);T--;){
            scanf("%d",&n);
            for(int i=0;i<=n;++i) head[i]=-1;
            for(int i=0;i<=n+1;++i) A[i]=B[i]=0;
            tot=0,dep[1]=t=1;
            for(int i=2;i<=n;++i)
            {
                scanf("%d",&x);add(x,i);
            }
            dfs(1);
            scanf("%d",&m);
            while(m--){
                scanf("%d%d",&op,&v);
                if(op==1){
                    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
    ",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+88;
    int L[N],R[N],dep[N],tot,t,head[N],fa[N],ans[N];
    struct et{
       int v,next;
    }e1[N<<2];
    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<<2];
    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<<1].w^=tr[rt].w;tr[rt<<1|1].w^=tr[rt].w;
        tr[rt].w=0;
       }
    }
    void build(int l,int r,int rt){
       tr[rt].l=l,tr[rt].r=r,tr[rt].w=0;
       if(l==r) return;
       int mid=(l+r)>>1;
       build(l,mid,rt<<1);
       build(mid+1,r,rt<<1|1);
    }
    void dfs(int u){
        L[u]=t++;
       for(int i=head[u];i+1;i=e1[i].next){
        int v=e1[i].v;
        if(v==fa[u]) continue;
        dep[v]=dep[u]+1;
        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)>>1;
       if(R<=mid) add(L,R,rt<<1,val);
       else if(L>mid) add(L,R,rt<<1|1,val);
       else {
        add(L,mid,rt<<1,val);
        add(mid+1,R,rt<<1|1,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)>>1;
        push_down(rt);
        if(pc<=mid) return query(pc,rt<<1);
        else return query(pc,rt<<1|1);
    }
    int main(){
        int T,n,m,u,v,w;
        for(scanf("%d",&T);T--;){
            scanf("%d",&n);
            build(1,n,1);
            memset(head,-1,sizeof(head));
            tot=0;
            t=1;
            for(int i=1;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(1);
            scanf("%d",&m);
            for(int i=1;i<=m;++i){
                scanf("%d%d%d",&e2[i].u,&e2[i].v,&e2[i].w);
                e2[i].id=i;
            }
            sort(sor+1,sor+n);
            sort(e2+1,e2+m+1);
            int ii=1;
            for(int i=1;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]-1,1,sor[ii].w);
                    ++ii;
                }
                int t1=query(L[e2[i].u],1),t2=query(L[e2[i].v],1);
                ans[e2[i].id]=t1^t2;
            }
            for(int i=1;i<=m;++i) printf("%d
    ",ans[i]);
        }
    }
     
     
     
     
     
     
     
     
     
     
    
    
    
  • 相关阅读:
    【ci框架】ci框架目录结构分析
    php CI框架
    jQuery boxy弹出层插件中文演示及讲解
    Jenkins构建报错(Jenkins is reserved for jobs with matching label expression)解决办法
    redis缓存数据架构实战
    Git免密码pull&push
    Maven搭建Nexus私有仓库
    Windows使用filezilla搭建FTP服务器
    CentOS7.4使用yum安装MySQL5.6
    MySQL数据库连接池导致页面登录无法查询问题解决过程
  • 原文地址:https://www.cnblogs.com/mfys/p/7252826.html
Copyright © 2020-2023  润新知