CF 396C On Changing Tree(线段树)

来源:互联网 发布:淘宝帐号注销 编辑:程序博客网 时间:2024/05/16 05:07

题意:给出一棵树,最开始每个节点权值都为0,有两种操作,一种是将点v加上x,对于它的子树中的点,加上x-i*k,i为该点到v的距离,第二个是查询点v的值。

思路:通过dfs,可以把树转化为一个区间[l,r],第一种操作实际上是x+k*(dep[v]-dep[u]),dep[]为该点到根节点的距离,u为v的子树。那么我们用两个线段树维护x+k*dep[v]和k的值,查询时两个值用第一个值减去第二个值×dep[v]就是结果了。

代码:

#include <iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<map>#include<queue>#include<stack>#include<cmath>#include<vector>#define inf 0x3f3f3f3f#define Inf 0x3FFFFFFFFFFFFFFFLL#define eps 1e-9#define pi acos(-1.0)using namespace std;typedef long long ll;const int maxn=300000+10;const int mod=1000000000+7;struct SegTree{    ll sum[maxn<<2],addv[maxn<<2];    void PushUp(int rt)    {        sum[rt]=sum[rt<<1]+sum[rt<<1|1];    }    void PushDown(int l,int r,int rt)    {        if(addv[rt])        {            int m=(l+r)>>1;            addv[rt<<1]=(addv[rt<<1]+addv[rt])%mod;            addv[rt<<1|1]=(addv[rt<<1|1]+addv[rt])%mod;            sum[rt<<1]=(sum[rt<<1]+(m-l+1)*addv[rt])%mod;            sum[rt<<1|1]=(sum[rt<<1|1]+(r-m)*addv[rt])%mod;            addv[rt]=0;        }    }    void build(int l,int r,int rt)    {        sum[rt]=addv[rt]=0;        if(l==r) return ;        int m=(l+r)>>1;        build(l,m,rt<<1);        build(m+1,r,rt<<1|1);    }    ll Query(int L,int R,int l,int r,int rt)    {        if(l>=L&&r<=R)            return sum[rt];        PushDown(l,r,rt);        int m=(l+r)>>1;        ll sum=0;        if(m>=L) sum+=Query(L,R,l,m,rt<<1);        if(m<R) sum+=Query(L,R,m+1,r,rt<<1|1);        return sum%mod;    }    void Update(int L,int R,int l,int r,int rt,ll v)    {        if(l>=L&&r<=R)        {            addv[rt]=(addv[rt]+v)%mod;            sum[rt]=(sum[rt]+(r-l+1)*v)%mod;            return;        }        PushDown(l,r,rt);        int m=(l+r)>>1;        if(m>=L) Update(L,R,l,m,rt<<1,v);        if(m<R) Update(L,R,m+1,r,rt<<1|1,v);        PushUp(rt);    }}t1,t2;struct Edge{    int v,next;    Edge(){}    Edge(int v,int next):v(v),next(next){}}edges[maxn<<1];int head[maxn],d[maxn],l[maxn],r[maxn],nEdge,dfs_clock;int n,q;void AddEdges(int u,int v){    edges[++nEdge]=Edge(v,head[u]);    head[u]=nEdge;    edges[++nEdge]=Edge(u,head[v]);    head[v]=nEdge;}void Init(){    memset(head,0xff,sizeof(head));    nEdge=-1;dfs_clock=0;    d[1]=0;    t1.build(1,n,1);    t2.build(1,n,1);}void dfs(int u,int fa){    l[u]=++dfs_clock;    for(int k=head[u];k!=-1;k=edges[k].next)    {        int v=edges[k].v;        if(v==fa) continue;        d[v]=d[u]+1;        dfs(v,u);    }    r[u]=dfs_clock;}int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    scanf("%d",&n);    Init();    int type,v,x,k;    for(int i=2;i<=n;++i)    {        scanf("%d",&v);        AddEdges(i,v);    }    dfs(1,-1);    scanf("%d",&q);    while(q--)    {        scanf("%d",&type);        if(type==1)        {            scanf("%d%d%d",&v,&x,&k);            t1.Update(l[v],r[v],1,n,1,x+(ll)k*d[v]%mod);            t2.Update(l[v],r[v],1,n,1,k);        }        else        {            scanf("%d",&v);            ll ans=t1.Query(l[v],l[v],1,n,1);            ans-=t2.Query(l[v],l[v],1,n,1)*d[v];            ans=(ans%mod+mod)%mod;            printf("%I64d\n",ans);        }    }    return 0;}


0 0
原创粉丝点击