• F


    题目链接:

    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
    ",ans);
    132             }
    133         }
    134     }
    135     return 0;
    136 }
  • 相关阅读:
    JAVA-AbstractQueuedSynchronizer-AQS
    线程封闭
    安全发布对象
    JAVA并发基础
    C#JsonConvert.DeserializeObject反序列化json字符
    Java并发容器
    JAVA简易数据连接池Condition
    Java线程读写锁
    JDK提供的原子类和AbstractQueuedSynchronizer(AQS)
    协方差矩阵分解的物理意义
  • 原文地址:https://www.cnblogs.com/letlifestop/p/10706339.html
Copyright © 2020-2023  润新知