zoukankan      html  css  js  c++  java
  • BZOJ-4034: [HAOI2015]树上操作 (线段树+DFS序)

    4034: [HAOI2015]树上操作

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 5879  Solved: 1897
    [Submit][Status][Discuss]

    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 。

    Source

    假装我过了←_← 辣鸡TLE
     1 #include "bits/stdc++.h"
     2 #define lson rt<<1,l,m
     3 #define rson rt<<1|1,m+1,r
     4 using namespace std;
     5 typedef long long LL;
     6 const int MAX=1e5+5;
     7 LL n,m,a[MAX];
     8 LL tot,head[MAX],adj[MAX],next[MAX];
     9 LL tx,cc[MAX],vv[MAX],fa[MAX];
    10 LL c[MAX<<2],la[MAX<<2];
    11 bool vis[MAX];
    12 inline LL read(){
    13     LL an=0,x=1;char c=getchar();
    14     while (c<'0' || c>'9') {if (c=='-') x=-1;c=getchar();}
    15     while (c>='0' && c<='9') {an=an*10+c-'0';c=getchar();}
    16     return an*x;
    17 }
    18 void addedge(int u,int v){tot++; adj[tot]=v; next[tot]=head[u]; head[u]=tot;}
    19 void PushUp(int rt){
    20     c[rt]=c[rt<<1]+c[rt<<1|1];
    21 }
    22 void PushDown(int rt,int l,int r){
    23     int m=(l+r)>>1;
    24     if (la[rt]){
    25         la[rt<<1]+=la[rt],la[rt<<1|1]+=la[rt];
    26         c[rt<<1]+=la[rt]*(m-l+1);
    27         c[rt<<1|1]+=la[rt]*(r-m);
    28         la[rt]=0;
    29     }
    30 }
    31 void update(int rt,int l,int r,int x,int y,LL z){
    32     if (x<=l && r<=y){
    33         la[rt]+=z; c[rt]+=(r-l+1)*z;
    34         return;
    35     }
    36     int m=(l+r)>>1;
    37     PushDown(rt,l,r);
    38     if (x<=m) update(lson,x,y,z);
    39     if (y>m) update(rson,x,y,z);
    40     PushUp(rt);
    41 }
    42 LL query(int rt,int l,int r,LL x){
    43     if (l==r && l==x)
    44         return c[rt];
    45     int m=(l+r)>>1;LL cnt=0;
    46     PushDown(rt,l,r);
    47     if (x<=m) cnt+=query(lson,x);
    48     else cnt+=query(rson,x);
    49     return cnt;
    50 }
    51 void dfs(int x){
    52     cc[x]=++tx;vis[x]=true;
    53     int i,j;
    54     for (i=head[x];i;i=next[i])
    55         if (!vis[adj[i]])
    56             fa[adj[i]]=x,dfs(adj[i]);
    57     vv[x]=tx;
    58 }
    59 LL calc(int x){
    60     if (x==1) return query(1,1,n,cc[x]);
    61     return query(1,1,n,cc[x])+calc(fa[x]);
    62 }
    63 int main(){
    64     freopen ("tree.in","r",stdin);
    65     freopen ("tree.out","w",stdout);
    66     int i,j,x,y,z,u,v;
    67     n=read(),m=read();
    68     for (i=1;i<=n;i++) a[i]=read();
    69     for (i=1;i<n;i++){
    70         u=read(),v=read();
    71         addedge(u,v),addedge(v,u);
    72     }
    73     fa[1]=0,dfs(1);
    74     for (i=1;i<=n;i++) update(1,1,n,cc[i],cc[i],a[i]);
    75     for (i=1;i<=m;i++){
    76         z=read();
    77         if (z==1) x=read(),y=read(),update(1,1,n,cc[x],cc[x],y);
    78         if (z==2) x=read(),y=read(),update(1,1,n,cc[x],vv[x],y);
    79         if (z==3) x=read(),printf("%lld
    ",calc(x));
    80     }
    81     return 0;
    82 }
    未来是什么样,未来会发生什么,谁也不知道。 但是我知道, 起码从今天开始努力, 肯定比从明天开始努力, 要快一天实现梦想。 千里之行,始于足下! ——《那年那兔那些事儿》
  • 相关阅读:
    [FJOI 2016] 神秘数
    [SHOI 2017] 寿司餐厅
    [HAOI 2012] Road
    [HAOI 2012] 容易题
    [TJOI 2018] XOR
    [NOI 2011] 阿狸的打字机
    [ZJOI 2010] 排列计数
    [TJOI2016 & HEOI2016] 字符串
    [HNOI 2011] 数学作业
    【NTT】loj#6261. 一个人的高三楼
  • 原文地址:https://www.cnblogs.com/keximeiruguo/p/7705232.html
Copyright © 2011-2022 走看看