zoukankan      html  css  js  c++  java
  • [HAOI2015]T2

    【题目描述】

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

    操作1:把某个节点x的点权增加a。

    操作2:把某个节点x为根的子树中所有点的点权都增加a。

    操作3:询问某个节点x到根的路径中所有点的点权和。

    【输入格式】

    第一行两个整数N,M,表示点数和操作数。

    接下来一行N个整数,表示树中节点的初始权值。

    接下来N-1行每行两个正整数fr,to,表示该树中存在一条边(fr,to)。

    再接下来M行,每行分别表示一次操作。其中第一个数表示该操作的种类(1~3),之后接这个操作的参数(x或者x a)。

    【输出格式】

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

    【样例输入】

    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

    【样例输出】

    6

    9

    13

    【提示】

    对于30%的数据,N,M<=1000

    对于50%的数据,N,M<=100000且数据随机。

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

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstdlib>
      4 #include<cstring>
      5 #include<cmath>
      6 #include<algorithm>
      7 #include<vector>
      8 #include<queue>
      9 using namespace std;
     10 typedef long long LL;
     11 const LL maxn=100010;
     12 inline LL read(){
     13     LL x=0,f=1;char ch=getchar();
     14     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     15     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
     16     return x*f;
     17 }
     18 vector<LL> to[maxn];
     19 LL N,M;
     20 LL a[maxn];
     21 LL dep[maxn],fa[maxn],son[maxn],top[maxn],siz[maxn],id[maxn];
     22 LL val[maxn];
     23 LL num;
     24 inline void dfs1(LL rt,LL fath,LL deep){
     25     dep[rt]=deep; siz[rt]=1; fa[rt]=fath;
     26     for(LL i=0;i<to[rt].size();i++){
     27         LL y=to[rt][i];
     28         if(y!=fa[rt]){
     29             dfs1(y,rt,deep+1);
     30             siz[rt]+=siz[y];
     31             if(siz[son[rt]]<siz[y]) son[rt]=y;
     32         }
     33     }
     34 }
     35 inline void dfs2(LL rt,LL tp){
     36     top[rt]=tp; id[rt]=++num;
     37     if(son[rt]!=0) dfs2(son[rt],tp);
     38     for(LL i=0;i<to[rt].size();i++){
     39         LL y=to[rt][i];
     40         if(y!=fa[rt]&&y!=son[rt]){
     41             dfs2(y,y);
     42         }
     43     }
     44 }
     45 struct node{
     46     LL l,r;
     47     LL sum,lazy;
     48 }tree[maxn*8];
     49 inline void build(LL rt,LL l,LL r){
     50     tree[rt].l=l; tree[rt].r=r;
     51     if(l==r){
     52         tree[rt].sum=val[l];
     53         tree[rt].lazy=0;
     54         return ;
     55     }
     56     LL mid=(l+r)>>1;
     57     build(rt<<1,l,mid); build(rt<<1|1,mid+1,r);
     58     tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum;
     59 }
     60 inline void update_son(LL rt){
     61     LL d=tree[rt].lazy;
     62     if(d!=0){
     63         tree[rt<<1].sum+=(tree[rt<<1].r-tree[rt<<1].l+1)*d;
     64         tree[rt<<1|1].sum+=(tree[rt<<1|1].r-tree[rt<<1|1].l+1)*d;
     65         tree[rt<<1].lazy+=d; tree[rt<<1|1].lazy+=d;
     66         tree[rt].lazy=0;
     67     }
     68 }
     69 inline void change(LL rt,LL l,LL r,LL delta){
     70     if(l<=tree[rt].l&&tree[rt].r<=r){
     71         tree[rt].sum+=(tree[rt].r-tree[rt].l+1)*delta;
     72         tree[rt].lazy+=delta;
     73         return ;
     74     }
     75     update_son(rt);
     76     LL mid=(tree[rt].l+tree[rt].r)>>1;
     77     if(l<=mid) change(rt<<1,l,r,delta);
     78     if(mid+1<=r) change(rt<<1|1,l,r,delta);
     79     tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum;
     80 }
     81 inline LL query(LL rt,LL l,LL r){
     82     if(l<=tree[rt].l&&tree[rt].r<=r){
     83         return tree[rt].sum;
     84     }
     85     update_son(rt);
     86     LL ans=0;
     87     LL mid=(tree[rt].l+tree[rt].r)>>1;
     88     if(l<=mid) ans+=query(rt<<1,l,r);
     89     if(mid+1<=r) ans+=query(rt<<1|1,l,r);
     90      return ans;
     91 }
     92 inline void ASK(LL x){
     93     LL tp=top[x],ans=0;
     94     while(x!=0&&tp!=0){
     95         ans+=query(1,id[tp],id[x]);
     96         x=fa[tp]; tp=top[x];
     97     }
     98     printf("%lld
    ",ans);
     99 }
    100 int main(){
    101     N=read(); M=read();
    102     for(LL i=1;i<=N;i++) a[i]=read();
    103     for(LL i=1,u,v;i<=N-1;i++){
    104         u=read(); v=read();
    105         to[u].push_back(v); to[v].push_back(u);
    106     }
    107     dis[1]=a[1];
    108     dfs1(1,0,1); dfs2(1,1);
    109     for(LL i=1;i<=N;i++) val[id[i]]=a[i];
    110     build(1,1,num);
    111     for(LL i=1,kin;i<=M;i++){
    112         kin=read();
    113         if(kin==1){
    114             LL x=read(),d=read();
    115             change(1,id[x],id[x],d);
    116         }
    117         else if(kin==2){
    118             LL x=read(),d=read();
    119             change(1,id[x],id[x]+siz[x]-1,d);
    120         }
    121         else if(kin==3){
    122             LL x=read();
    123             ASK(x);
    124         }
    125     }
    126     return 0;
    127 }
  • 相关阅读:
    数据挖掘十大经典算法
    vc++17 进程间的通信
    GOOGLE笔试题(10.15电子科大)
    解决Vmware下Linux上网问题
    Eclipse 常用快捷键
    Error: could not open `C:\Program Files\Java\jre6\lib\i386\jvm.cfg')
    linux下ERROR 1045 (28000): Access denied for user root@localhost (using password: NO)
    eclipse环境变量设置
    为什么写博客
    eclipse添加自动代码提示
  • 原文地址:https://www.cnblogs.com/CXCXCXC/p/5022114.html
Copyright © 2011-2022 走看看