zoukankan      html  css  js  c++  java
  • bzoj4034:[HAOI2015]树上操作

    Description

    有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个
    操作,分为三种:
    操作 1 :把某个节点 x 的点权增加 a 。
    操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
    操作 3 :询问某个节点 x 到根的路径中所有点的点权和。

    Input

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

    Output

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

     

    Sample Input

    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

    Sample Output

    6
    9
    13

    HINT

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

    题解:

    明明就是一道树链剖分模板题啊啊啊啊……

    RE了无数次,简直是醉了,最后发现……有一个数组名是rank,大概是和库中某个函数名重了,改成rk就AC了……

    好吧,言归正传

    操作1对应到线段树中的单点修改

    操作2因为以某节点为根的子树的编号都应该是连续的,所以可以对应到线段树中的区间修改

    之前求重子时不是记过一个size吗,在这里就可以用来知道子树编号的范围

    操作3比较常规,求路径上的和

    还有中间求和操作要开long long,否则也会RE

    注意:就是容器名称呵,最好有“个性”一些,千万不要和其他东西重了

    代码:

      1 #include<iostream>
      2 #include<cstdio>
      3 using namespace std;
      4 
      5 const int MAXN=200005;
      6 struct node
      7 {
      8     int v;
      9     node *next;       
     10 }pool[MAXN],*h[MAXN];
     11 int cnt,tot;
     12 int fa[MAXN],dep[MAXN],size[MAXN],son[MAXN];
     13 int rk[MAXN],w[MAXN],top[MAXN],val[MAXN];
     14 
     15 void addedge(int u,int v)
     16 {
     17     node *p=&pool[++cnt],*q=&pool[++cnt];
     18     p->v=v;p->next=h[u];h[u]=p;    
     19     q->v=u;q->next=h[v];h[v]=q;
     20 }
     21 void dfs1(int u)
     22 {
     23     int v;
     24     size[u]=1;
     25     int Bson=0,sonnum=0;
     26     for(node *p=h[u];p;p=p->next)
     27         if(fa[u]!=(v=p->v))
     28         {
     29             fa[v]=u;
     30             dep[v]=dep[u]+1;
     31             dfs1(v);
     32             size[u]+=size[v];
     33             if(size[v]>Bson) Bson=size[v],sonnum=v;                   
     34         }
     35     son[u]=sonnum;
     36 }
     37 void dfs2(int u)
     38 {
     39     int v=son[u];
     40     if(v)
     41     {
     42         top[v]=top[u];
     43         rk[v]=++tot;
     44         w[rk[v]]=val[v];
     45         dfs2(v);    
     46     }
     47     for(node *p=h[u];p;p=p->next)
     48         if(fa[v=p->v]==u && v!=son[u])
     49         {
     50             top[v]=v;
     51             rk[v]=++tot;
     52             w[rk[v]]=val[v];
     53             dfs2(v);                 
     54         }
     55 }
     56 
     57 struct tree
     58 {
     59     int l,r;
     60     long long sum,lazy;
     61     tree *left,*right;       
     62 }t[4*MAXN],*root;
     63 int cnt1;
     64 void pushdown(tree *p)
     65 {
     66     if(p->lazy)
     67     {
     68         p->sum+=p->lazy*(long long)(p->r-p->l+1);
     69         if(p->left) p->left->lazy+=p->lazy;
     70         if(p->right) p->right->lazy+=p->lazy;
     71         p->lazy=0;
     72     }
     73 }
     74 void update(tree *p)
     75 {
     76     p->sum=0;
     77     if(p->left) p->sum+=p->left->sum+p->left->lazy*(long long)(p->left->r-p->left->l+1);
     78     if(p->right) p->sum+=p->right->sum+p->right->lazy*(long long)(p->right->r-p->right->l+1);     
     79 }
     80 void Build_Tree(tree *p,int l,int r)
     81 {
     82     p->l=l;p->r=r;
     83     if(l==r)
     84     {
     85         p->sum=(long long)w[l];
     86         return;
     87     }
     88     int mid=(l+r)/2;
     89     p->left=&t[++cnt1];p->right=&t[++cnt1];
     90     Build_Tree(p->left,l,mid);
     91     Build_Tree(p->right,mid+1,r);
     92     p->sum=p->left->sum+p->right->sum;
     93 }
     94 void change(tree *p,int l,int r,int c)
     95 {
     96     if(p->l==l && p->r==r)
     97     {
     98         p->lazy+=(long long)c;
     99         return;
    100     }
    101     pushdown(p);
    102     if(p->left->r>=r) change(p->left,l,r,c);
    103     else if(p->right->l<=l) change(p->right,l,r,c);
    104     else change(p->left,l,p->left->r,c),change(p->right,p->right->l,r,c);
    105     update(p);
    106 }
    107 long long query(tree *p,int l,int r)
    108 {
    109     if(p->l==l && p->r==r)
    110         return p->sum+p->lazy*(p->r-p->l+1);
    111     pushdown(p);
    112     if(p->left->r>=r) return query(p->left,l,r);
    113     else if(p->right->l<=l) return query(p->right,l,r);
    114     else return query(p->left,l,p->left->r)+query(p->right,p->right->l,r);
    115 }
    116 
    117 long long Sum(int x,int y)
    118 {
    119     long long ret=0;
    120     int f1=top[x],f2=top[y];
    121     while(f1!=f2)
    122     {
    123         if(dep[f1]<dep[f2]) swap(f1,f2),swap(x,y);
    124         ret+=query(root,rk[f1],rk[x]);
    125         x=fa[f1];f1=top[x];        
    126     }
    127     if(dep[x]>dep[y]) swap(x,y);
    128     ret+=query(root,rk[x],rk[y]);
    129     return ret;
    130 }
    131 
    132 int main()
    133 {
    134     int n,m,i,a,b,c;
    135     scanf("%d%d",&n,&m);
    136     for(i=1;i<=n;i++) scanf("%d",&val[i]);
    137     for(i=1;i<n;i++)
    138         scanf("%d%d",&a,&b),addedge(a,b);
    139     
    140     dfs1(1);
    141     top[1]=1;rk[1]=++tot;w[rk[1]]=val[1];
    142     dfs2(1);
    143     root=&t[++cnt1];Build_Tree(root,1,n);
    144     
    145     while(m --> 0)
    146     {
    147         scanf("%d",&c);
    148         if(c==1)
    149             scanf("%d%d",&a,&b),change(root,rk[a],rk[a],b);
    150         else if(c==2)
    151             scanf("%d%d",&a,&b),change(root,rk[a],rk[a]+size[a]-1,b);
    152         else
    153             scanf("%d",&a),printf("%lld
    ",Sum(1,a));
    154     }
    155     
    156     return 0;
    157 }
    View Code
    既然选择了远方,便只顾风雨兼程
  • 相关阅读:
    第一阶段冲刺02
    梦断代码阅读笔记01
    第一阶段冲刺01
    第十周总结报告
    单词统计
    用户模板分析
    第九周总结
    第九周课后作业
    py_11_ 0726
    Day_01
  • 原文地址:https://www.cnblogs.com/lindalee/p/7217868.html
Copyright © 2011-2022 走看看