F - Change FZU - 2277 (DFS序+线段树)

题目链接:

F - Change

 FZU - 2277 

题目大意:

题意: 给定一棵根为1, n个结点的树. 有q个操作,有两种不同的操作

(1) 1 v k x : a[v] += x, a[v '] += x – k(v '为v的儿子), a[v ' '] += x – 2 * k(v ' '是v '的儿子) ... ;

(2) 2 v : 输出a[v] % (1e9 + 7);

具体思路:dfs序+线段树

a[v'']=a[v'']+x-k*(depth[v'']-depth[v])=a[v'']+x-k*depth[v"]+k*depth[v]=(a[v"]+k*depth[v]) - k*depth[v""].

第一个括号里面用一个线段树维护,第二个括号里面用另一个线段树维护就可以了。

具体求值的时候:对于一次增加操作,节点x增加的值其实就是x-(deep[x]-deep[v])*k。(deep[v]为该次修改的根节点)。

AC代码:

  1 #include<iostream>
  2 #include<stdio.h>
  3 #include<vector>
  4 #include<cstring>
  5 using namespace std;
  6 # define ll long long
  7 # define lson l,mid,rt<<1
  8 # define rson mid+1,r,rt<<1|1
  9 const int maxn = 3e5+100;
 10 const int mod  =1e9+7;
 11 ll tree1[maxn<<2],tree2[maxn<<2];
 12 int dfsord,n;
 13 vector<int>edge[maxn];
 14 int st[maxn],ed[maxn],depth[maxn];
 15 int Scan()
 16 {
 17     int res = 0, ch, flag = 0;
 18     if((ch = getchar()) == '-')
 19         flag = 1;
 20     else if(ch >= '0' && ch <= '9')
 21         res = ch - '0';
 22     while((ch = getchar()) >= '0' && ch <= '9' )
 23         res = res * 10 + ch - '0';
 24     return flag ? -res : res;
 25 }
 26 
 27 ll Scan_l()
 28 {
 29     ll res = 0;
 30     int ch, flag = 0;
 31     if((ch = getchar()) == '-')
 32         flag = 1;
 33     else if(ch >= '0' && ch <= '9')
 34         res = ch - '0';
 35     while((ch = getchar()) >= '0' && ch <= '9' )
 36         res = res * 10 + ch - '0';
 37     return flag ? -res : res;
 38 }
 39 void init()
 40 {
 41     for(int i=0; i<n; i++)
 42     {
 43         edge[i].clear();
 44     }
 45     dfsord=0;
 46     memset(tree1,0,sizeof(tree1));
 47     memset(tree2,0,sizeof(tree2));
 48 }
 49 void dfs(int cur,int fa,int dep)
 50 {
 51     st[cur]=ed[cur]=++dfsord;
 52     depth[dfsord]=dep+1;
 53     for(int i=0; i<edge[cur].size(); i++)
 54     {
 55         int to=edge[cur][i];
 56         if(to==fa)
 57             continue;
 58         dfs(to,cur,dep+1);
 59     }
 60     ed[cur]=dfsord;
 61 }
 62 void down(int rt)
 63 {
 64     tree1[rt<<1]=(tree1[rt<<1]+tree1[rt]+mod)%mod;
 65     tree1[rt<<1|1]=(tree1[rt<<1|1]+tree1[rt]+mod)%mod;
 66     tree2[rt<<1]=(tree2[rt<<1]+tree2[rt]+mod)%mod;
 67     tree2[rt<<1|1]=(tree2[rt<<1|1]+tree2[rt]+mod)%mod;
 68     tree1[rt]=0,tree2[rt]=0;
 69 }
 70 void update(int l,int r,int rt,int L,int R,ll val1,ll val2)
 71 {
 72     if(L<=l&&R>=r)
 73     {
 74         tree1[rt]=(tree1[rt]+val1+mod)%mod;
 75         tree2[rt]=(tree2[rt]+val2+mod)%mod;
 76         return ;
 77     }
 78     down(rt);
 79     int mid=(l+r)>>1;
 80     if(L<=mid)
 81         update(lson,L,R,val1,val2);
 82     if(R>mid)
 83         update(rson,L,R,val1,val2);
 84 }
 85 ll ask(int l,int r,int rt,int pos)
 86 {
 87     if(l==r)
 88     {
 89         return (tree1[rt]+tree2[rt]*depth[pos]%mod+mod)%mod;
 90     }
 91     int mid=(l+r)>>1;
 92     down(rt);
 93     if(pos<=mid)
 94         return ask(lson,pos);
 95     else
 96         return ask(rson,pos);
 97 }
 98 int main()
 99 {
100     int T,tmp;
101     T=Scan();
102     while(T--)
103     {
104         n=Scan();
105         init();
106         for(int i=2; i<=n; i++)
107         {
108             tmp=Scan();
109             edge[tmp].push_back(i);
110         }
111         int m;
112         dfs(1,0,0);
113         m=Scan();
114         while(m--)
115         {
116             int op,v;
117             ll x,k;
118             op=Scan();
119             if(op==1)
120             {
121                 v=Scan();
122                 x=Scan_l();
123                 k=Scan_l();
124                 update(1,n,1,st[v],ed[v],x+k*depth[st[v]],-k);
125             }
126             else
127             {
128                 v=Scan();
129                 ll ans=ask(1,n,1,st[v]);
130                 ans=(ans%mod+mod)%mod;
131                 printf("%lld\n",ans);
132             }
133         }
134     }
135     return 0;
136 }

 

posted @ 2019-04-14 18:24  Let_Life_Stop  阅读(254)  评论(0编辑  收藏  举报