zoukankan      html  css  js  c++  java
  • 洛谷P3178 [HAOI2015]树上操作

    树剖板子QwQ

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #define maxn 100010
    
    using namespace std;
    
    typedef long long ll;
    struct node
    {
        ll ed,nxt;
    };
    node edge[maxn<<1];
    long long n,m,first[maxn],cnt;
    long long num[maxn],num_rnk[maxn];
    long long dep[maxn],fa[maxn],siz[maxn],son[maxn],rnk[maxn],top[maxn],seg[maxn];
    long long rnk_cnt,ans,tot;
    long long tree[maxn<<2],tag[maxn<<2];
    
    inline void add_edge(ll s,ll e)
    {
        ++cnt;
        edge[cnt].ed=e;
        edge[cnt].nxt=first[s];
        first[s]=cnt;
        return;
    }
    
    inline void dfs_1(ll now,ll pre)
    {
        dep[now]=dep[pre]+1; fa[now]=pre; siz[now]=1;
        for(register int i=first[now];i;i=edge[i].nxt)
        {
            ll e=edge[i].ed;
            if(e==fa[now]) continue;
            dfs_1(e,now);
            siz[now]+=siz[e];
            if(son[now]==-1||siz[e]>siz[son[now]]) son[now]=e;
        }
        return;
    }
    
    inline void dfs_2(ll now,ll heavy_fa)
    {
        top[now]=heavy_fa;
        ++rnk_cnt;
        rnk[now]=rnk_cnt; seg[rnk_cnt]=now; num_rnk[rnk_cnt]=num[now];
        if(son[now]==-1) return;
        dfs_2(son[now],heavy_fa);
        for(register int i=first[now];i;i=edge[i].nxt)
        {
            ll e=edge[i].ed;
            if(e!=fa[now]&&e!=son[now]) dfs_2(e,e);
        }
        return;
    }
    
    inline void build(ll k,ll l,ll r)
    {
        if(l==r)
        {
            tree[k]=num_rnk[l];
            return;
        }
        ll mid=(l+r)>>1,son=k<<1;
        build(son,l,mid); build(son|1,mid+1,r);
        tree[k]=tree[son]+tree[son|1];
        return;
    }
    
    inline void push_down(ll k,ll l,ll r)
    {
        ll mid=(l+r)>>1,son=k<<1;
        tree[son]+=(mid-l+1)*tag[k]; tag[son]+=tag[k];
        tree[son|1]+=(r-mid)*tag[k]; tag[son|1]+=tag[k];
        tag[k]=0;
        return;
    }
    
    inline void modify(ll k,ll l,ll r,ll x,ll y,long long v)
    {
        if(r<x||l>y) return;
        if(x<=l&&r<=y)
        {
            tree[k]+=v*(r-l+1);
            tag[k]+=v;
            return;
        }
        if(tag[k]) push_down(k,l,r);
        ll mid=(l+r)>>1,son=k<<1;
        modify(son,l,mid,x,y,v); modify(son|1,mid+1,r,x,y,v);
        tree[k]=tree[son]+tree[son|1];
        return;
    }
    
    inline void get_sum(int k,int l,ll r,ll x,int y)
    {
        if(r<x||l>y) return;
        if(x<=l&&r<=y)
        {
            tot+=tree[k];
            return;
        }
        if(tag[k]) push_down(k,l,r);
        ll mid=(l+r)>>1,son=k<<1;
        get_sum(son,l,mid,x,y); get_sum(son|1,mid+1,r,x,y);
        tree[k]=tree[son]+tree[son|1];
        return;
    }
    
    inline void tree_sum(int x,int y)
    {
        while(top[x]!=top[y])
        {
            if(dep[top[x]]<dep[top[y]]) swap(x,y);
            tot=0;
            get_sum(1,1,n,rnk[top[x]],rnk[x]);
            ans+=tot;
            x=fa[top[x]];
        }
        tot=0;
        get_sum(1,1,n,min(rnk[x],rnk[y]),max(rnk[x],rnk[y]));
        ans+=tot;
        return;
    }
    
    int main()
    {
        scanf("%lld%lld",&n,&m);
        for(register int i=1;i<=n;++i)
            scanf("%lld",&num[i]);
        for(register int i=1;i<=n-1;++i)
        {
            ll s,e;
            scanf("%lld%lld",&s,&e);
            add_edge(s,e);
            add_edge(e,s);
        }
        memset(son,-1,sizeof(son));
        dfs_1(1,0);
        dfs_2(1,1);
        build(1,1,n);
        for(register int i=1;i<=m;++i)
        {
            ll opt;
            scanf("%lld",&opt);
            if(opt==1)
            {
                ll x;
                long long v;
                scanf("%lld%lld",&x,&v);
                modify(1,1,n,rnk[x],rnk[x],v);
            }
            else if(opt==2)
            {
                ll x;
                long long v;
                scanf("%lld%lld",&x,&v);
                modify(1,1,n,rnk[x],rnk[x]+siz[x]-1,v);
            }
            else if(opt==3)
            {
                ll x;
                scanf("%lld",&x);
                ans=0;
                tree_sum(1,x);
                printf("%lld
    ",ans);
            }
        }
        return 0;
    } 
  • 相关阅读:
    Hadoop学习笔记—20.网站日志分析项目案例(二)数据清洗
    python四舍五入保留2位小数
    查看python中的keywords(关键字)和modules
    c:forEach实现动态select标签
    解决Windows上数据库密码忘记问题
    Java读取properties文件总结
    URL地址最大长度问题
    Servlet生命周期
    解决mysql 数据库连接密码
    Java中int与integer的区别
  • 原文地址:https://www.cnblogs.com/Hoyoak/p/11816981.html
Copyright © 2011-2022 走看看