• HAOI2015 树上操作


    题目描述

    题解:

    线段树维护dfs序。

    貌似是裸题。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define N 100050
    #define ll long long
    inline int rd()
    {
        int f=1,c=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=10*c+ch-'0';ch=getchar();}
        return f*c;
    }
    int n,m,hed[N],cnt=0;
    struct EG
    {
        int to,nxt;
    }e[2*N];
    void ae(int f,int t)
    {
        e[++cnt].to = t;
        e[cnt].nxt = hed[f];
        hed[f] = cnt;
    }
    int a[N];
    int tin[N],tout[N],tim,k[N<<1],K[N<<1];
    void dfs(int u,int fa)
    {
        tin[u] = ++tim;k[tim]=1;K[tim]=a[u];
        for(int j=hed[u];j;j=e[j].nxt)
        {
            int to = e[j].to;
            if(to==fa)continue;
            dfs(to,u);
        }
        tout[u]=++tim;k[tim]=-1;K[tim]=-a[u];
    }
    struct segtree
    {
        ll v[N<<3],tag[N<<3],siz[N<<3];
        void add(int u,ll d)
        {
            tag[u]+=d;
            v[u]+=d*siz[u];
        }
        void pushdown(int u)
        {
            if(tag[u])
            {
                add(u<<1,tag[u]);
                add(u<<1|1,tag[u]);
                tag[u]=0;
            }
        }
        void update(int u)
        {
            v[u] = v[u<<1]+v[u<<1|1]+siz[u]*tag[u];
        }
        void build(int l,int r,int u)
        {
            if(l==r)
            {
                siz[u]=k[l];
                v[u] = K[l];
                tag[u]=0;
                return ;
            }
            int mid = (l+r)>>1;
            build(l,mid,u<<1);
            build(mid+1,r,u<<1|1);
            siz[u] = siz[u<<1]+siz[u<<1|1];
            update(u);
        }
        void insert(int l,int r,int u,int ql,int qr,ll d)
        {
            if(l==ql&&r==qr)
            {
                add(u,d);
                return ;
            }
            pushdown(u);
            int mid = (l+r)>>1;
            if(qr<=mid)insert(l,mid,u<<1,ql,qr,d);
            else if(ql>mid)insert(mid+1,r,u<<1|1,ql,qr,d);
            else insert(l,mid,u<<1,ql,mid,d),insert(mid+1,r,u<<1|1,mid+1,qr,d);
            update(u);
        }
        ll query(int l,int r,int u,int ql,int qr)
        {
            if(l==ql&&r==qr)return v[u];
            pushdown(u);
            int mid = (l+r)>>1;
            if(qr<=mid)return query(l,mid,u<<1,ql,qr);
            else if(ql>mid)return query(mid+1,r,u<<1|1,ql,qr);
            else return query(l,mid,u<<1,ql,mid)+query(mid+1,r,u<<1|1,mid+1,qr);
        }
    }tr;
    int main()
    {
        n=rd(),m=rd();
        for(int i=1;i<=n;i++)
        {
            a[i]=rd();
        }
        for(int f,t,i=1;i<n;i++)
        {
            f=rd(),t=rd();
            ae(f,t),ae(t,f);
        }
        dfs(1,0);
        tr.build(1,tim,1);
        for(int typ,x,y,i=1;i<=m;i++)
        {
            typ=rd();
            if(typ==1)
            {
                x=rd(),y=rd();
                tr.insert(1,tim,1,tin[x],tin[x],y);
                tr.insert(1,tim,1,tout[x],tout[x],y);
            }else if(typ==2)
            {
                x=rd(),y=rd();
                tr.insert(1,tim,1,tin[x],tout[x],y);
            }else if(typ==3)
            {
                x=rd();
                ll ans = tr.query(1,tim,1,1,tin[x]);
                printf("%lld
    ",ans);
            }else break;
        }
        return 0;
    }
  • 相关阅读:
    【leetcode】11. 盛最多水的容器
    【leetcode】8. 字符串转换整数 (atoi)
    【leetcode】6. Z 字形变换
    【leetcode】5. 最长回文子串
    【leetcode】LCP 19. 秋叶收藏集
    删除第一个节点问题
    问一个大学学习计算机这门专业的问题
    Struts文件上传页面上传后显示“连接已重置”
    2013-12-6 思杨没吃饱 饿醒了
    2013-12-7 snoopy乐园中的思杨
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10155165.html
Copyright © 2020-2023  润新知