• 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;
    }
  • 相关阅读:
    从零开始入门 K8s | 应用编排与管理
    209. Minimum Size Subarray Sum
    208. Implement Trie (Prefix Tree)
    207. Course Schedule
    203. Remove Linked List Elements
    183. Customers Who Never Order
    182. Duplicate Emails
    181. Employees Earning More Than Their Managers
    1261. Find Elements in a Contaminated Binary Tree
    1260. Shift 2D Grid
  • 原文地址:https://www.cnblogs.com/wang9897/p/8393988.html
Copyright © 2020-2023  润新知