• bzoj4034 [HAOI2015]T2


      首先求出树的dfs序,对于第一种操作和第二种操作分开处理,第一种操作比较经典,就不说了。第二种操作其实和第一种也很类似,查询x点到根的权值和sum(x)=(disx+1)*v(x)-w,其中disx为x点到根的距离,v(x)表示以x到根之间的点为第二类操作的子树根所进行操作的权值和,这样相乘明显会有多余的部分,假设对y点进行第二类操作,使其和其子树上的点增加z,那么会多计算价值disy*z,使用两颗树状数组维护即可。

      代码

      

     1 #include<cstdio>
     2 #define nc getchar
     3 #define N 1000010
     4 int tot,n,m,i,v[N],dp,p[N],pre[N],tt[N],L[N],R[N],a,b,T;
     5 long long c[N][3],dis[N],ans;
     6 inline int lowbit(int x)
     7 {
     8     return x&(-x);
     9 }
    10 void cc(int x,long long w,int typ)
    11 {
    12     while (x<=tot)
    13     {
    14         c[x][typ]+=w;
    15         x+=lowbit(x);
    16     }
    17 }
    18 long long sum(int x,int typ)
    19 {
    20     long long ans=0;
    21     while (x)
    22     {
    23         ans+=c[x][typ];
    24         x-=lowbit(x);
    25     }
    26     return ans; 
    27 }
    28 void link(int x,int y)
    29 {
    30     dp++;pre[dp]=p[x];p[x]=dp;tt[dp]=y;
    31 }
    32 void dfs(int x,int fa)
    33 {
    34     int i=p[x];
    35     tot++;L[x]=tot;
    36     while (i)
    37     {
    38         if (tt[i]!=fa)
    39         {
    40             dis[tt[i]]=dis[x]+1;
    41             dfs(tt[i],x);
    42         }
    43         i=pre[i];
    44     }
    45     tot++;R[x]=tot;
    46 }
    47 int main()
    48 {
    49     scanf("%d%d",&n,&m);
    50     for (i=1;i<=n;i++)
    51     scanf("%d",&v[i]);
    52     for (i=1;i<n;i++)
    53     {
    54         scanf("%d%d",&a,&b);
    55         link(a,b);link(b,a);
    56     }
    57     dfs(1,0);
    58     for (i=1;i<=n;i++)
    59     {
    60         cc(L[i],v[i],0);
    61         cc(R[i],-v[i],0);
    62     }
    63     for (i=1;i<=m;i++)
    64     {
    65         scanf("%d",&T);
    66         if (T==1)
    67         {
    68             scanf("%d%d",&a,&b);
    69             cc(L[a],b,0);
    70             cc(R[a],-b,0);
    71         }
    72         else
    73         if (T==2)
    74         {
    75             scanf("%d%d",&a,&b);
    76             cc(L[a],b,1);
    77             cc(R[a],-b,1);
    78             cc(L[a],dis[a]*(long long)b,2);
    79             cc(R[a],-dis[a]*(long long)b,2);
    80         }
    81         else
    82         {
    83             scanf("%d",&a);
    84             ans=sum(L[a],0)-sum(L[a],2)+sum(L[a],1)*(dis[a]+1);
    85             printf("%lld
    ",ans);
    86         }
    87     }
    88     
    89 }
  • 相关阅读:
    编写可读性代码的艺术
    web前端常见的加密算法介绍
    git 遇到的问题
    Vue.js使用proxytable跨域的路径问题
    设置动画元素
    解决echarts图表在显示没有数据后再切换后渲染不出的问题
    svn回滚到之前的版本
    插件用法--视频播放video.js
    网页适配
    不跳转页面下载文件
  • 原文地址:https://www.cnblogs.com/fzmh/p/5392429.html
Copyright © 2020-2023  润新知