zoukankan      html  css  js  c++  java
  • 【BZOJ4034】【HAOI2015】树上操作

    题目请自行查阅传送门

    典型的树剖题,线段树维护操作,记一下子树在线段树内范围即可。

    时间复杂度:( O(m log^{2} n) )

    #include <stdio.h>
    #define MN 100005
    #define Mn (1<<17)
    #define ls (k<<1)
    #define rs (k<<1|1)
    #define mid (l+r>>1)
    #define ll long long
    ll sum[Mn<<1],mark[Mn<<1];
    int val[MN],siz[MN],dep[MN],fa[MN],top[MN],son[MN],head[MN],l[MN],r[MN],n,q,cnt,dfsn,root=1;
    struct tree{int to,nxt;}edge[MN<<1];
    inline int in(){
        int x=0,f=1;
        char ch=getchar();
        while (ch<'0'||ch>'9') f=ch=='-'?-1:1,ch=getchar();
        while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
        return x*f;
    }
    inline void ins(int x,int y){edge[++cnt].to=y,edge[cnt].nxt=head[x],head[x]=cnt;}
    inline void dfs1(int u,int f,int d){
        siz[u]=1,dep[u]=d,fa[u]=f;
        for (register int i=head[u]; i; i=edge[i].nxt)
            if (edge[i].to!=f){
                dfs1(edge[i].to,u,d+1);siz[u]+=siz[edge[i].to];
                if (siz[edge[i].to]>siz[son[u]]) son[u]=edge[i].to;
            }
    }
    inline void dfs2(int u,int tp){
        top[u]=tp,l[u]=(++dfsn);if (son[u]) dfs2(son[u],tp);
        for (register int i=head[u]; i; i=edge[i].nxt)
            if (edge[i].to!=son[u]&&edge[i].to!=fa[u]) dfs2(edge[i].to,edge[i].to); r[u]=dfsn;
    }
    inline void pushdown(int k,int l,int r){
        if (l==r||!mark[k]) return;register int x=r-l+1;
        mark[ls]+=mark[k],mark[rs]+=mark[k];
        sum[ls]+=(x-(x>>1))*mark[k];sum[rs]+=(x>>1)*mark[k];mark[k]=0;
    }
    inline void combine(int k){sum[k]=sum[ls]+sum[rs];}
    inline void A(int l,int r,int a,int b,int k,int ad){
        if (a<=l&&r<=b){mark[k]+=ad;sum[k]+=1ll*ad*(r-l+1);return;}
        pushdown(k,l,r);if (a<=mid) A(l,mid,a,b,ls,ad);
        if (b>mid) A(mid+1,r,a,b,rs,ad);combine(k);
    }
    inline ll Q(int l,int r,int a,int b,int k){
        if (l==a&&r==b) return sum[k];pushdown(k,l,r);
        if (b<=mid) return Q(l,mid,a,b,ls);
        if (a>mid) return Q(mid+1,r,a,b,rs);
        return Q(l,mid,a,mid,ls)+Q(mid+1,r,mid+1,b,rs);
    }
    inline ll query(int x){
        register ll res=0;
        while (top[x]!=root) res+=Q(1,n,l[top[x]],l[x],1),x=fa[top[x]];
        return res+=Q(1,n,l[root],l[x],1); 
    }
    void init(){
        n=in(),q=in();for (int i=1; i<=n; ++i) val[i]=in();
        for (register int i=1; i<n; ++i){
            register int x=in(),y=in();
            ins(x,y); ins(y,x);
        }
        dfs1(root,1,1);dfs2(root,root);
        for (register int i=1; i<=n; ++i) A(1,n,l[i],l[i],1,val[i]);
    }
    void solve(){
        while(q--){
            register int op=in(),x=in(),ad;
            if (op^3){
                ad=in();if (op&1) A(1,n,l[x],l[x],1,ad);
                else A(1,n,l[x],r[x],1,ad);
             }else printf("%lld
    ",query(x));
        }
    }
    int main(){init(); solve(); return 0;}
  • 相关阅读:
    js封装日期格式化函数
    原生js时间戳获取和转换
    自适应好用的一个css
    ES6五种遍历对象属性的方式
    ES6对象属性名简洁表示法和表达式、对象新方法、属性的遍历
    ES6数组扩展运算符(Rest+Spread)、类方法、原型方法
    正则表达式常见匹配
    typescript深copy和浅copy
    判断一个变量类型是对象还是数组
    npm 淘宝镜像的配置
  • 原文地址:https://www.cnblogs.com/Melacau/p/BZOJ4034.html
Copyright © 2011-2022 走看看