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

    大概树链剖分裸题吧(没开ll  WA了两发

    4034: [HAOI2015]树上操作

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 6360  Solved: 2109
    [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
    #include <bits/stdc++.h>
    #define N 100005
    #define ll long long
    using namespace std;
    int son[N],num[N],dep[N],fa[N];
    int cnt,p[N],fp[N],tp[N],a[N],n,m;
    vector<int>vec[N];
    int read(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return f*x;
    }
    void dfs1(int v,int pre,int deep){
        num[v]=1;fa[v]=pre;dep[v]=deep+1;
        for(int i=0;i<vec[v].size();i++){
            if(vec[v][i]!=pre){
                dfs1(vec[v][i],v,deep+1);
                num[v]+=num[vec[v][i]];
                if(son[v]==-1||num[son[v]]<num[vec[v][i]]){
                    son[v]=vec[v][i];
                }
            }
        }
    }
    void dfs2(int v,int td){
        p[v]=++cnt;fp[cnt]=v;tp[v]=td;
        if(son[v]!=-1) dfs2(son[v],td);
        for(int i=0;i<vec[v].size();i++){
            if(vec[v][i]!=fa[v]&&vec[v][i]!=son[v]) dfs2(vec[v][i],vec[v][i]);
        }
    }
    typedef struct node{
        int l,r;
        ll flag;
        ll sum;
    }node;
    node d[N<<2];
    void update_add(int x,ll vul){
        d[x].flag+=vul;d[x].sum+=1ll*(d[x].r-d[x].l+1)*vul;
    }
    void push(int x){
        if(d[x].flag){
            update_add(x<<1,d[x].flag);
            update_add(x<<1|1,d[x].flag);
            d[x].flag=0;
        }
    }
    void up(int x){
        d[x].sum=d[x<<1].sum+d[x<<1|1].sum;
    }
    void built(int root,int l,int r){
        if(l==r){
            d[root].l=d[root].r=l;d[root].sum=a[fp[l]];d[root].flag=0;
            return ;
        }
        int mid=(l+r)>>1;
        built(root<<1,l,mid);
        built(root<<1|1,mid+1,r);
        d[root].l=d[root<<1].l;d[root].r=d[root<<1|1].r;d[root].flag=0;
        up(root);
    }
    void update(int root,int l,int r,int t){
        if(l<=d[root].l&&d[root].r<=r){
            update_add(root,t);
            return ;
        }
        push(root);
        int mid=(d[root].l+d[root].r)>>1;
        if(l<=mid) update(root<<1,l,r,t);
        if(r>mid) update(root<<1|1,l,r,t);
        up(root);
    }
    ll ans1;
    void querty(int root,int l,int r){
        if(l<=d[root].l&&d[root].r<=r){
            ans1+=d[root].sum;
            return ;
        }
        int mid=(d[root].l+d[root].r)>>1;
        push(root);
        if(l<=mid) querty(root<<1,l,r);
        if(r>mid) querty(root<<1|1,l,r);
        up(root);
    }
    ll Sum(int v){
        ll ans=0;int vv=tp[v];
        while(tp[v]!=1){
            ans1=0;querty(1,p[vv],p[v]);
            ans+=ans1;
            v=fa[vv];vv=tp[v];
        }
        ans1=0;querty(1,1,p[v]);
        ans+=ans1;
        return ans;
    }
    int main(){
        ios::sync_with_stdio(false);
        n=read();m=read();cnt=0;
        for(int i=1;i<=n;i++) a[i]=read();
        for(int i=1;i<=n;i++) son[i]=-1;
        int t1,t2,op;
        for(int i=1;i<n;i++){
            t1=read();t2=read();
            vec[t1].push_back(t2);
            vec[t2].push_back(t1);
        }
        dfs1(1,0,0);
        dfs2(1,1);
        built(1,1,n);
        for(int i=1;i<=m;i++){
            op=read();
            if(op==1){
                t1=read();t2=read();
                update(1,p[t1],p[t1],t2);
            }
            else if(op==2){
                t1=read();t2=read();
                update(1,p[t1],p[t1]+num[t1]-1,t2);
            }
            else{
                t1=read();
                printf("%lld
    ",Sum(t1));
            }
        }
        return 0;
    }
  • 相关阅读:
    [笔记]: 树链剖分 2017-06-05 16:57 35人阅读 评论(0) 收藏
    [笔记]: 最小生成树Kruska 2017-06-05 16:52 34人阅读 评论(0) 收藏
    [笔记]: 并查集 2017-06-05 16:49 58人阅读 评论(0) 收藏
    [bzoj2144]: 跳跳棋 2017-06-02 15:53 42人阅读 评论(0) 收藏
    [noip2013] 货车运输(最大生成树+并查集+LCA) 2017-06-02 15:18 56人阅读 评论(0) 收藏
    [练习] LCA练习1(最基础) 2017-06-02 11:54 39人阅读 评论(0) 收藏
    [笔记]: RMQ算法(区间查询) 2017-06-01 18:06 44人阅读 评论(0) 收藏
    [笔记]: LCA最近公共祖先 2017-06-01 11:38 38人阅读 评论(0) 收藏
    [hdu&poj&洛谷] 经典线段树练习题 2017-06-01 08:10 56人阅读 评论(0) 收藏
    保留X位小数(Double) swift
  • 原文地址:https://www.cnblogs.com/wang9897/p/8393988.html
Copyright © 2011-2022 走看看