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

    题目描述

    有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个操作,分为三种:操作 1 :把某个节点 x 的点权增加 a 。操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。操作 3 :询问某个节点 x 到根的路径中所有点的点权和。

    输入输出格式

    输入格式:

    第一行包含两个整数 N, M 。表示点数和操作数。接下来一行 N 个整数,表示树中节点的初始权值。接下来 N-1 行每行三个正整数 fr, to , 表示该树中存在一条边 (fr, to) 。再接下来 M 行,每行分别表示一次操作。其中第一个数表示该操作的种类( 1-3 ) ,之后接这个操作的参数( x 或者 x a ) 。

    输出格式:

    对于每个询问操作,输出该询问的答案。答案之间用换行隔开。

    输入输出样例

    输入样例#1:
    5 5
    1 2 3 4 5
    1 2
    1 4
    2 3
    2 5
    3 3
    1 2 1
    3 5
    2 1 2
    3 3
    输出样例#1:
    6
    9
    13

    说明

    对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不

    会超过 10^6 。

    树剖裸题

    俩小时。。卧槽!

    别用scanf读long long 的负数!

    别用scanf读long long 的负数!

    别用scanf读long long 的负数!

    屠龙宝刀点击就送

    #include <iostream>
    #include <ctype.h>
    #include <cstdio>
    #define N 200005
    #define M 100005
    using namespace std;
    typedef long long LL;
    struct Tree
    {
        LL l,r,dis,lazy;
    }tr[N<<2|1];
    struct node
    {
        LL next,to;
    }edge[N<<1];
    LL dfn[M],dis[M],n,m,root,p,top[M],belong[M],tim,head[M],cnt,fa[M],dep[M],size[M];
    void add(LL u,LL v)
    {
        edge[++cnt].next=head[u];
        edge[cnt].to=v;
        head[u]=cnt;
    }
    void dfs1(LL now)
    {
        dep[now]=dep[fa[now]]+1;
        size[now]=1;
        for(LL i=head[now];i;i=edge[i].next)
        {
            LL v=edge[i].to;
            if(fa[now]!=v)
            {
                fa[v]=now;
                dfs1(v);
                size[now]+=size[v];
            }
        }
    }
    void dfs2(LL now)
    {
        belong[now]=++tim;
        dfn[tim]=now;
        LL t=0;
        if(!top[now]) top[now]=now;
        for(LL i=head[now];i;i=edge[i].next)
        {
            LL v=edge[i].to;
            if(fa[now]!=v&&size[t]<size[v]) t=v;
        }
        if(t) top[t]=top[now],dfs2(t);
        for(LL i=head[now];i;i=edge[i].next)
        {
            LL v=edge[i].to;
            if(fa[now]!=v&&v!=t) dfs2(v);
        }
    }
    void up(LL k) {tr[k].dis=tr[k<<1].dis+tr[k<<1|1].dis ;} 
    void build(LL k,LL l,LL r)
    {
        tr[k].l=l;
        tr[k].r=r;
        if(l==r)
        {
            tr[k].dis=dis[dfn[l]];
            return;
        }
        LL mid=(l+r)>>1;
        build(k<<1,l,mid);
        build(k<<1|1,mid+1,r);
        up(k); 
    }
    void swap(LL &a,LL &b)
    {
        LL tmp=b;
        b=a;
        a=tmp;
    }
    void pushdown(LL k)
    {
        if(tr[k].l==tr[k].r) return;
        tr[k<<1].lazy+=tr[k].lazy;
        tr[k<<1|1].lazy+=tr[k].lazy;
        tr[k<<1].dis=tr[k<<1].dis+(tr[k<<1].r-tr[k<<1].l+1)*tr[k].lazy;
        tr[k<<1|1].dis=tr[k<<1|1].dis+(tr[k<<1|1].r-tr[k<<1|1].l+1)*tr[k].lazy;
        tr[k].lazy=0;
    }
    void Tree_change(LL k,LL l,LL r,LL z)
    {
        if(tr[k].l==l&&tr[k].r==r)
        {
            tr[k].lazy+=z;
            tr[k].dis=tr[k].dis+(r-l+1)*z;
            return;
        }
        if(tr[k].lazy) pushdown(k);
        LL mid=(tr[k].l+tr[k].r)>>1;
        if(l>mid) Tree_change(k<<1|1,l,r,z);
        else if(r<=mid) Tree_change(k<<1,l,r,z);
        else Tree_change(k<<1,l,mid,z),Tree_change(k<<1|1,mid+1,r,z);
        up(k);
    }
    LL Tree_query(LL k,LL l,LL r)
    {
        if(tr[k].lazy) pushdown(k);
        if(tr[k].l==l&&tr[k].r==r)
            return tr[k].dis;
        LL mid=(tr[k].l+tr[k].r)>>1;
        if(l>mid) return Tree_query(k<<1|1,l,r);
        else if(r<=mid) return Tree_query(k<<1,l,r);
        else return (Tree_query(k<<1,l,mid)+Tree_query(k<<1|1,mid+1,r));
        up(k); 
    }
    void Chain_change(LL x,LL y,LL z)
    {
        for(;top[x]!=top[y];x=fa[top[x]])
        {
            if(dep[top[x]]<dep[top[y]]) swap(x,y);
            Tree_change(1,belong[top[x]],belong[x],z);
        }
        if(dep[x]<dep[y]) swap(x,y);
        Tree_change(1,belong[y],belong[x],z);
    }
    LL Chain_query(LL x,LL y)
    {
        LL ans=0;
        for(;top[x]!=top[y];x=fa[top[x]])
        {
            if(dep[top[x]]<dep[top[y]]) swap(x,y);
            ans=(ans+Tree_query(1,belong[top[x]],belong[x])); 
        }
        if(dep[x]<dep[y]) swap(x,y);
        ans=(ans+Tree_query(1,belong[y],belong[x]));
        return ans;
    }
    void read(LL &x)
    {
        x=0;bool f=0;
        char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') f=1;ch=getchar();}
        while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
        x=f?-x:x; 
    }
    int main()
    {
        read(n);read(m);
        for(LL i=1;i<=n;i++) read(dis[i]);
        for(LL x,y,i=1;i<n;i++)
        {
            read(x);read(y);
            add(x,y);
            add(y,x);
        }
        dfs1(1);
        dfs2(1);
        build(1,1,n);
        for(LL opt,x,a;m--;)
        {
            read(opt);
            if(opt==1)
            {
                read(x);read(a);
                Tree_change(1,belong[x],belong[x],a);
            }
            else if(opt==2)
            {
                read(x);read(a);
                Tree_change(1,belong[x],belong[x]+size[x]-1,a);
            }
            else if(opt==3)
            {
                read(x);
                cout<<Chain_query(1,x)<<endl;
            }
        }
        return 0;
    }
    我们都在命运之湖上荡舟划桨,波浪起伏着而我们无法逃脱孤航。但是假使我们迷失了方向,波浪将指引我们穿越另一天的曙光。
  • 相关阅读:
    获取表信息(MSSQL)
    合并有数据的列
    isnull的使用方法
    查询SQLServer的启动时间
    查询数据库中有数据的表
    查询数据库中表使用的空间信息。
    SQL Server SA 密码丢失无法连接数据库怎么办?
    tensorflow 语法及 api 使用细节
    Python: PS 滤镜-- Fish lens
    中英文对照 —— 概念的图解
  • 原文地址:https://www.cnblogs.com/ruojisun/p/7194965.html
Copyright © 2011-2022 走看看