zoukankan      html  css  js  c++  java
  • [HAOI2015]树上操作(树链剖分)

    原题

    BZOJ
    洛谷

    Solution

    直接很简单的树链剖分然后搞一个线段树维护一下就好了?

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<math.h>
    #include<algorithm>
    #include<iostream>
    #include<queue>
    #define ll long long
    #define file(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
    using namespace std;
    inline int gi(){
        int sum=0,f=1;char ch=getchar();
        while(ch>'9' || ch<'0'){if(ch=='-')f=-f;ch=getchar();}
        while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
        return f*sum;
    }
    inline ll gl(){
        ll sum=0,f=1;char ch=getchar();
        while(ch>'9' || ch<'0'){if(ch=='-')f=-f;ch=getchar();}
        while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
        return f*sum;
    }
    const int maxn=500010;
    ll old[maxn];int to[maxn<<1],nxt[maxn<<1],front[maxn],cnt;ll w[maxn];
    int siz[maxn],fa[maxn],dep[maxn],son[maxn],top[maxn],b[maxn],n;
    struct node{
        int l,r;ll add,val;
    }tree[maxn<<4];
    void Add(int u,int v){
        to[++cnt]=v;nxt[cnt]=front[u];front[u]=cnt;
    }
    void dfs1(int u,int f){
        siz[u]=1;fa[u]=f;dep[u]=dep[f]+1;
        for(int i=front[u];i;i=nxt[i]){
            int v=to[i];
            if(v!=fa[u]){
                dfs1(v,u);
                siz[u]+=siz[v];
                if(siz[v]>siz[son[u]])son[u]=v;
            }
        }
    }
    void dfs2(int u,int tp){
        top[u]=tp;b[u]=++cnt;w[cnt]=old[u];
        if(!son[u])return;
        dfs2(son[u],tp);
        for(int i=front[u];i;i=nxt[i]){
            int v=to[i];
            if(v!=son[u] && v!=fa[u])dfs2(v,v);
        }
    }
    void pushup(int o){
        tree[o].val=tree[o<<1].val+tree[o<<1|1].val;
    }
    
    void build(int o,int l,int r){
        tree[o].l=l;tree[o].r=r;tree[o].add=0;
        if(l==r){
    		tree[o].val=w[l];
    		return;
    	}
        int mid=(l+r)>>1;
        build(o<<1,l,mid);build(o<<1|1,mid+1,r);
        pushup(o);
    }
    void pushdown(int o){
        if(tree[o].add){
            tree[o<<1].add+=tree[o].add;
            tree[o<<1|1].add+=tree[o].add;
            tree[o<<1].val+=tree[o].add*(tree[o<<1].r-tree[o<<1].l+1);
            tree[o<<1|1].val+=tree[o].add*(tree[o<<1|1].r-tree[o<<1|1].l+1);
            tree[o].add=0;
        }
    }
    void update(int o,int l,int r,int posl,int posr,ll k){
        if(posl<=l && r<=posr){
            tree[o].val+=k*(r-l+1);tree[o].add+=k;
            return;
        }
        pushdown(o);
        int mid=(l+r)>>1;
        if(mid>=posr)update(o<<1,l,mid,posl,posr,k);
        else if(mid<posl)update(o<<1|1,mid+1,r,posl,posr,k);
        else{
            update(o<<1,l,mid,posl,mid,k);
            update(o<<1|1,mid+1,r,mid+1,posr,k);
        }
        pushup(o);
    }
    ll query(int o,int l,int r,int posl,int posr){
        if(posl<=l && r<=posr)return tree[o].val;
        pushdown(o);
        int mid=(l+r)>>1;
        if(mid>=posr)return query(o<<1,l,mid,posl,posr);
        else if(mid<posl)return query(o<<1|1,mid+1,r,posl,posr);
        return query(o<<1,l,mid,posl,mid)+query(o<<1|1,mid+1,r,mid+1,posr);
    }
    ll Query(int u,int v){
    	ll ans=0;
        while(top[u]!=top[v]){
            if(dep[top[u]]<dep[top[v]])swap(u,v);
            ans+=query(1,1,n,b[top[u]],b[u]);u=fa[top[u]];
        }
        if(dep[u]>dep[v])swap(u,v);
        return ans+query(1,1,n,b[u],b[v]);
    }
    int main(){
        int i,j,m,k;
        n=gi();m=gi();
        for(i=1;i<=n;i++)old[i]=gi();
        for(i=1;i<n;i++){
            int u=gi(),v=gi();
            Add(u,v);Add(v,u);
        }
        cnt=0;
        dfs1(1,1);dfs2(1,1);
        build(1,1,n);
        while(m--){
            int x,a,opt;cin>>opt>>x;
            if(opt==1){
                cin>>a;
                update(1,1,n,b[x],b[x],a);
            }
            else if(opt==2){
                cin>>a;
                update(1,1,n,b[x],b[x]+siz[x]-1,a);
            }
            else printf("%lld
    ",Query(1,x));
        }
        return 0;
    }
    
  • 相关阅读:
    对于工程师责任和责任边界的认知
    windows消息机制与实例
    final阶段团队贡献分分配
    Final阶段用户调查报告
    对金州勇士团队的项目进行功能分解(加分作业)
    final review 报告
    final发布评论
    本周PSP
    final发布视频
    【转】mac版微信web开发者工具(小程序开发工具)无法显示二维码 解决方案
  • 原文地址:https://www.cnblogs.com/cjgjh/p/9833302.html
Copyright © 2011-2022 走看看