zoukankan      html  css  js  c++  java
  • 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]);
        }
    }
     
     
     
     
     
     
     
     
     
     
    
    
    
  • 相关阅读:
    Swift3 重写一个带占位符的textView
    Swift3 使用系统UIAlertView方法做吐司效果
    Swift3 页面顶部实现拉伸效果代码
    Swift3 倒计时按钮扩展
    iOS 获取当前对象所在的VC
    SpringBoot在IDEA下使用JPA
    hibernate 异常a different object with the same identifier value was already associated with the session
    SpringCloud IDEA 教学 番外篇 后台运行Eureka服务注册中心
    SpringCloud IDEA 教学 (五) 断路器控制台(HystrixDashboard)
    SpringCloud IDEA 教学 (四) 断路器(Hystrix)
  • 原文地址:https://www.cnblogs.com/mfys/p/7252826.html
Copyright © 2011-2022 走看看