zoukankan      html  css  js  c++  java
  • luogu P3178 [HAOI2015]树上操作

    题目

    题目描述

    有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个操作,分为三种:

    • 操作 1 :把某个节点 x 的点权增加 a 。
    • 操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
    • 操作 3 :询问某个节点 x 到根的路径中所有点的点权和。

    输入格式

    第一行包含两个整数 N, M 。表示点数和操作数。
    接下来一行 N 个整数,表示树中节点的初始权值。
    接下来 N-1 行每行两个正整数 from, to , 表示该树中存在一条边 (from, to) 。
    再接下来 M 行,每行分别表示一次操作。其中第一个数表示该操作的种类( 1-3 ) ,之后接这个操作的参数( x 或者 x a ) 。

    输出格式

    对于每个询问操作,输出该询问的答案。答案之间用换行隔开。

    输入输出样例

    输入 #1
    5 5
    1 2 3 4 5
    1 2
    1 4
    2 3
    2 5
    3 3
    1 2 1
    3 5
    2 1 2
    3 3
    输出 #1
    6
    9
    13

    说明/提示

    对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不会超过 10^6 。

     

    分析

     

    • 首先,我们要知道dfs序
    • 就是一颗树进出栈的顺序
    • 然后我们记录下他们的时间戳
    • 就知道他们的左右子树在哪个区间
    • 然后用线段树维护
    • 还有一个重要的点是
    • 我们可以发现1-x点就是x进栈的前缀
    • 考虑如何维护线段树
    • 首先我们是有x和-x的,我们要一个前缀数组搞出区间正x的个数
    • 对于第一个修改x+=x -x+=-x就好了
    • 然后主要区间加一定打lazy
    • lazy的return 是如果数在区间里面的
    • 然后还有

      if (a<=mid) ans+=find(k<<1,a,b);
      if (b>=mid+1) ans+=find(k<<1|1,a,b); 别忘了

     

    代码

      1 #include<iostream>
      2 #include<cstdio>
      3 #define ll long long
      4 using namespace std;
      5 ll a[500001];
      6 struct sb
      7 {
      8     ll l,r,sum,bz,add;
      9 }t[2*200001];
     10 ll id[500001],num,le[500001],ri[500001],vis[500001],ss[500001];
     11 struct node
     12 {
     13     ll to,nx;
     14 }g[2*200010];
     15 ll list[2*200010],cnt;
     16 void add(ll x,ll y)
     17 {
     18     g[++cnt].to=y; g[cnt].nx=list[x]; list[x]=cnt;
     19     g[++cnt].to=x; g[cnt].nx=list[y]; list[y]=cnt;
     20 }
     21 ll val[500001],v,flag[500001];
     22 inline ll read(){
     23     ll x=0,f=1;
     24     char ch=getchar();
     25     while(ch<'0'||ch>'9'){
     26         if(ch=='-')
     27             f=-1;
     28         ch=getchar();
     29     }
     30     while(ch>='0'&&ch<='9'){
     31         x=(x<<1)+(x<<3)+(ch^48);
     32         ch=getchar();
     33     }
     34     return x*f;
     35 }
     36 void dfs(ll x)
     37 {
     38     vis[x]=1;
     39     id[x]=++num;
     40     val[num]=a[x];
     41     flag[num]=1;
     42     le[x]=num;
     43     for (int i=list[x];i;i=g[i].nx)
     44     {
     45         ll y=g[i].to;
     46         if (!vis[y])
     47             dfs(y);
     48     }
     49     ri[x]=++num;
     50     val[num]=-a[x];
     51     flag[num]=-1;
     52 }
     53 void build(ll k,ll a,ll b)
     54 {
     55     t[k].l=a; t[k].r=b;
     56     if (a==b)
     57     {
     58         t[k].sum=val[a];
     59         t[k].bz=flag[a];
     60         return;
     61     }
     62     ll mid=a+b>>1;
     63     build(k<<1,a,mid);
     64     build(k<<1|1,mid+1,b);
     65     t[k].sum=t[k<<1].sum+t[k<<1|1].sum;
     66     t[k].bz=t[k<<1].bz+t[k<<1|1].bz;
     67 }
     68 void change(ll k,ll mb,ll z)
     69 {
     70     t[k].sum+=z; 
     71     if (t[k].l==t[k].r) return;
     72     ll mid=t[k].l+t[k].r>>1;
     73     if (mb<=mid) change(k<<1,mb,z);
     74     else change(k<<1|1,mb,z);
     75 }
     76 void lazy(ll k,ll a,ll b,ll m)
     77 {
     78     if (t[k].add!=0)
     79     {
     80         t[k<<1].add+=t[k].add;
     81         t[k<<1|1].add+=t[k].add;
     82         t[k<<1].sum=t[k<<1].sum+t[k].add*(ss[m]-ss[a-1]);
     83         t[k<<1|1].sum=t[k<<1|1].sum+t[k].add*(ss[b]-ss[m]);
     84         t[k].add=0;
     85     }
     86 }
     87 void change2(ll k,ll a,ll b,ll z)
     88 {
     89     if (a<=t[k].l&&b>=t[k].r)
     90     {
     91         t[k].add+=z;
     92         t[k].sum=t[k].sum+z*(ss[t[k].r]-ss[t[k].l-1]);
     93         return;
     94     }
     95     ll mid=(t[k].l+t[k].r)>>1;
     96     lazy(k,t[k].l,t[k].r,mid);
     97     if (a<=mid) change2(k<<1,a,b,z);
     98     if (b>=mid+1) change2(k<<1|1,a,b,z);
     99     t[k].sum=t[k<<1].sum+t[k<<1|1].sum;
    100 }
    101 ll find(ll k,ll a,ll b)
    102 {
    103     if (t[k].l>=a&&t[k].r<=b)
    104       return t[k].sum;
    105     ll mid=t[k].l+t[k].r>>1;
    106     ll ans=0; 
    107     lazy(k,t[k].l,t[k].r,mid);
    108     if (a<=mid) ans+=find(k<<1,a,b);
    109     if (b>=mid+1) ans+=find(k<<1|1,a,b);
    110     return ans; 
    111 }
    112 int main ()
    113 {
    114     ll n,m;
    115     n=read(); m=read();
    116     for (int i=1;i<=n;i++)
    117       a[i]=read();
    118     for (int i=1,x,y;i<=n-1;i++)
    119     {
    120         x=read(); y=read();
    121         add(x,y);
    122     }
    123     dfs(1);
    124     for (int i=1;i<=num;i++)
    125       ss[i]=ss[i-1]+flag[i];
    126     build(1,1,2*n);
    127     for (int i=1,op,x,y;i<=m;i++)
    128     {
    129         op=read();
    130         if (op==1)
    131         {
    132             x=read(); y=read();
    133             change(1,le[x],y);
    134             change(1,ri[x],-y);
    135         }
    136         if (op==2)
    137         {
    138             x=read(); y=read();
    139             change2(1,le[x],ri[x],y);
    140         }
    141         if (op==3)
    142         {
    143             x=read();
    144             printf("%lld
    ",find(1,1,le[x]));
    145         }
    146     }
    147 }

     

  • 相关阅读:
    昨天是下了一整天的雨,在家里买了一斤肉和恶小白菜吃
    昨天网上感觉好冷,睡在席子上都是感觉打哈欠
    今天是下雨了,看来是要穿长裤上班了
    昨天用的流量有点多60M
    Python常用模块(3)—— shelve、pickle、json、xml、configparser
    Python常用模块(2)—— os、sys、shutil
    Python常用模块(1)—— time、datetime、randrom
    内置函数
    包的导入使用
    模块的导入使用
  • 原文地址:https://www.cnblogs.com/zjzjzj/p/11379377.html
Copyright © 2011-2022 走看看