zoukankan      html  css  js  c++  java
  • BZOJ 4034 洛谷3178 树上操作题解

    一个很裸的树链剖分模板。注意一下数据范围,有的地方要开longlong,这就是唯一的陷阱了。

    # include<iostream>
    # include<cstdio>
    # include<cmath>
    # include<algorithm>
    using std::max;
    using std::min;
    const int mn = 100005;
    typedef long long LL;
    struct edge{int to,next;};
    edge e[mn*2];
    int edge_max,head[mn];
    void add(int x,int y)
    {
        e[++edge_max].to=y;
        e[edge_max].next=head[x];
        head[x]=edge_max;
    }
    int n,m;
    int val[mn];
    int fa[mn],siz[mn];
    void dfs1(int x)
    {
        siz[x]=1;
        for(int i=head[x];i;i=e[i].next)
        {
           int v=e[i].to;
           if(v==fa[x])
             continue;
           fa[v]=x;
           dfs1(v);
           siz[x]+=siz[v];
        }
    }
    int tot,id[mn],bl[mn],mx[mn];
    void dfs2(int x,int chain)
    {
        int k=0;
        ++tot;
        id[x]=mx[x]=tot;
        bl[x]=chain;
        for(int i=head[x];i;i=e[i].next)
        {
            if(e[i].to!=fa[x] && siz[e[i].to]>siz[k])
                k=e[i].to;
        }
        if(k==0)
            return ;
        dfs2(k,chain);
        mx[x]=max(mx[x],mx[k]);
        for(int i=head[x];i;i=e[i].next)
        {
            if(fa[x]!=e[i].to && e[i].to!=k)
            {
                dfs2(e[i].to,e[i].to);
                mx[x]=max(mx[x],mx[e[i].to]);
            }
        }
    }
    struct node{int l,r;LL sum,tag;};
    node tr[mn*4];
    inline void pushdown(int cur)
    {
        if(tr[cur].tag && tr[cur].l!=tr[cur].r)
        {
            tr[cur<<1].tag+=tr[cur].tag;
            tr[cur<<1|1].tag+=tr[cur].tag;
            tr[cur<<1].sum+=(tr[cur<<1].r-tr[cur<<1].l+1)*tr[cur].tag;
            tr[cur<<1|1].sum+=(tr[cur<<1|1].r-tr[cur<<1|1].l+1)*tr[cur].tag;
            tr[cur].tag=0;
        }
    }
    void build(int l,int r,int cur)
    {
        tr[cur].l=l,tr[cur].r=r;
        if(l==r)
        {
            return ;
        }
        int mid=l+r>>1;
        build(l,mid,cur<<1);
        build(mid+1,r,cur<<1|1);
    }
    void update(int cur,int l,int r,LL x)//此处要开longlong防止下面爆掉
    {
        if(tr[cur].r<l || tr[cur].l>r)
            return ;
        pushdown(cur);
        if(tr[cur].l>=l && tr[cur].r<=r)
        {
            tr[cur].sum+=(tr[cur].r-tr[cur].l+1)*x;//就是这里容易爆掉
            tr[cur].tag+=x;
            return ;
        }
        update(cur<<1,l,r,x);
        update(cur<<1|1,l,r,x);
        tr[cur].sum=tr[cur<<1].sum+tr[cur<<1|1].sum;
    }
    LL qsum(int cur,int l,int r)
    {
        if(tr[cur].r<l || tr[cur].l>r)
            return 0;
        pushdown(cur);
        if(tr[cur].l>=l && tr[cur].r<=r)
          return tr[cur].sum;
        LL tmp=0;
        tmp+=qsum(cur<<1,l,r);
        tmp+=qsum(cur<<1|1,l,r);
        tr[cur].sum=tr[cur<<1].sum+tr[cur<<1|1].sum;
        return tmp;
    }
    void querry(int x)
    {
        LL ans=0;
        while(bl[x]!=1)
        {
            ans+=qsum(1,id[bl[x]],id[x]);
            x=fa[bl[x]];
        }
        ans+=qsum(1,1,id[x]);
        printf("%lld
    ",ans);
    }
    int main()
    {
        int opt,x,y;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%d",&val[i]);
        for(int i=1;i<n;i++)
        {
            scanf("%d%d",&x,&y);
            add(x,y);
            add(y,x);
        }
        dfs1(1);
        dfs2(1,1);
        build(1,n,1);
        for(int i=1;i<=n;i++)
            update(1,id[i],id[i],val[i]);
        for(int i=1;i<=m;i++)
        {
           scanf("%d",&opt);
           if(opt==1)
           {
               scanf("%d%d",&x,&y);
               update(1,id[x],id[x],y*1ll);
           }
           else if(opt==2)
           {
               scanf("%d%d",&x,&y);
               update(1,id[x],mx[x],y*1ll);
           }
           else {
            scanf("%d",&x);
            querry(x);
           }
        }
        return 0;
    }
    

      

  • 相关阅读:
    【郑轻邀请赛 G】密室逃脱
    【郑轻邀请赛 C】DOBRI
    【郑轻邀请赛 F】 Tmk吃汤饭
    【郑轻邀请赛 I】这里是天堂!
    【郑轻邀请赛 B】base64解密
    【郑轻邀请赛 A】tmk射气球
    【郑轻邀请赛 H】 维克兹的进制转换
    解决adb command not found以及sdk环境配置
    adb shell 命令详解,android, adb logcat
    Unexpected exception 'Cannot run program ... error=2, No such file or directory' ... adb'
  • 原文地址:https://www.cnblogs.com/logeadd/p/8723651.html
Copyright © 2011-2022 走看看