• [bzoj1984]月下“毛景树”


    Description

    毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园。毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里。爬啊爬~爬啊爬~~毛毛虫爬到了一颗小小的“毛景树”下面,发现树上长着他最爱吃的毛毛果~~~

    “毛景树”上有$N$个节点和$N-1$条树枝,但节点上是没有毛毛果的,毛毛果都是长在树枝上的。但是这棵“毛景树”有着神奇的魔力,他能改变树枝上毛毛果的个数:

      $Change;k;w$:将第$k$条树枝上毛毛果的个数改变为$w$个。

      $Cover;u;v;w$:将节点$u$与节点$v$之间的树枝上毛毛果的个数都改变为$w$个。

      $Add;u;v;w$:将节点$u$与节点$v$之间的树枝上毛毛果的个数都增加$w$个。

    由于毛毛虫很贪,于是他会有如下询问:

      $Max;u;v$:询问节点$u$与节点$v$之间树枝上毛毛果个数最多有多少个。

    Input

    第一行一个正整数$N$。

    接下来$N-1$行,每行三个正整数$U_i,V_i$和$W_i$,第$i+1$行描述第$i$条树枝。表示第$i$条树枝连接节点$U_i$和节点$V_i$,树枝上有$W_i$个毛毛果。

    接下来是操作和询问,以“$Stop$”结束。

    Output

    对于毛毛虫的每个询问操作,输出一个答案。

    Sample Input

    4
    1 2 8
    1 3 7
    3 4 9
    Max 2 4
    Cover 2 4 5
    Add 1 4 10
    Change 1 16
    Max 2 4
    Stop

    Sample Output

    9
    16

    HINT

    $1;leq;N;leq;10^5$,操作+询问数目$;leq;10^5$。

    保证在任意时刻,所有树枝上毛毛果的个数都不会超过$10^9$个。

    Solution

    把边权转化成边的两端点中深度较大的那个点的点权.

    树剖+线段树(注意下传$lazy$的细节,以及没被覆盖时值不该是$0$,因为存在全覆盖成$0$的情况)

    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<stack>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #define N 100005
    #define M 300005
    using namespace std;
    struct linetree{
        int l,r,m,c,a;
    }lt[M];
    struct graph{
        int nxt,to,w,n;
    }e[M];
    char c[10];
    int g[N],a[N],b[N],w[N],n,u,v,x,cnt;
    int f[N],p[N],dep[N],siz[N],son[N],top[N];
    inline void addedge(int x,int y,int w,int n){
        e[++cnt].nxt=g[x];g[x]=cnt;
        e[cnt].to=y;e[cnt].w=w;e[cnt].n=n;
    }
    inline void dfs1(int u){
        int m=0;siz[u]=1;
        for(int i=g[u];i;i=e[i].nxt)
            if(!dep[e[i].to]){
                f[e[i].to]=u;
                a[e[i].to]=e[i].w;
                b[e[i].n]=e[i].to; 
                dep[e[i].to]=dep[u]+1;
                dfs1(e[i].to);
                siz[u]+=siz[e[i].to];
                if(siz[e[i].to]>m){
                    m=siz[e[i].to];
                    son[u]=e[i].to;
                }
            }
    }
    inline void dfs2(int u,int tp){
        top[u]=tp;p[u]=++cnt;w[cnt]=a[u];
        if(son[u]) dfs2(son[u],tp);
        for(int i=g[u];i;i=e[i].nxt)
            if(f[u]!=e[i].to&&son[u]!=e[i].to)
                dfs2(e[i].to,e[i].to);
    }
    inline void build(int u,int l,int r){
        lt[u].l=l;lt[u].r=r;lt[u].c=-1;
        if(lt[u].l<lt[u].r){
            int lef=u<<1,rig=u<<1|1;
            int mid=(lt[u].l+lt[u].r)>>1;
            build(lef,l,mid);build(rig,mid+1,r);
            lt[u].m=max(lt[lef].m,lt[rig].m);
        }
        else lt[u].m=w[lt[u].l];
    }
    inline void push(int u){
        int lef=u<<1,rig=u<<1|1;
        if(lt[u].c>=0){
            lt[lef].a=lt[rig].a=0;
            lt[lef].c=lt[rig].c=lt[u].c;
            lt[lef].m=lt[rig].m=lt[u].c;
            lt[u].c=-1;
        }
        if(lt[u].a){
            lt[lef].a+=lt[u].a;
            lt[rig].a+=lt[u].a;
            lt[lef].m+=lt[u].a;
            lt[rig].m+=lt[u].a;
            lt[u].a=0;
        }
    }
    inline void cover(int u,int l,int r,int k){
        if(lt[u].l>=l&&lt[u].r<=r){
            lt[u].m=lt[u].c=k;lt[u].a=0;
        }
        else if(lt[u].l<lt[u].r){
            int lef=u<<1,rig=u<<1|1;
            int mid=(lt[u].l+lt[u].r)>>1;
            push(u);
            if(l<=mid) cover(lef,l,r,k);
            if(r>mid) cover(rig,l,r,k);
            lt[u].m=max(lt[lef].m,lt[rig].m);
        }
    }
    inline void add(int u,int l,int r,int k){
        if(lt[u].l>=l&&lt[u].r<=r){
            lt[u].m+=k;lt[u].a+=k;
        }
        else if(lt[u].l<lt[u].r){
            int lef=u<<1,rig=u<<1|1;
            int mid=(lt[u].l+lt[u].r)>>1;
            push(u);
            if(l<=mid) add(lef,l,r,k);
            if(r>mid) add(rig,l,r,k);
            lt[u].m=max(lt[lef].m,lt[rig].m);
        }
    }
    inline int ask(int u,int l,int r){
        if(lt[u].l>=l&&lt[u].r<=r)
            return lt[u].m;
        if(lt[u].l<lt[u].r){
            int lef=u<<1,rig=u<<1|1,ret=0;
            int mid=(lt[u].l+lt[u].r)>>1;
            push(u);
            if(l<=mid) ret=max(ret,ask(lef,l,r));
            if(r>mid) ret=max(ret,ask(rig,l,r));
            return ret;
        }
    }
    inline void cov(int x,int y,int k){
        int lt;
        while(top[x]!=top[y]){
            if(dep[top[x]]<dep[top[y]]){
                lt=x;x=y;y=lt;
            }
            cover(1,p[top[x]],p[x],k);
            x=f[top[x]];
        }
        if(p[x]>p[y]){
            lt=x;x=y;y=lt;
        }
        if(p[x]<p[y]) cover(1,p[x]+1,p[y],k);
    }
    inline void ad(int x,int y,int k){
        int lt;
        while(top[x]!=top[y]){
            if(dep[top[x]]<dep[top[y]]){
                lt=x;x=y;y=lt;
            }
            add(1,p[top[x]],p[x],k);
            x=f[top[x]];
        }
        if(p[x]>p[y]){
            lt=x;x=y;y=lt;
        }
        if(p[x]<p[y]) add(1,p[x]+1,p[y],k);
    }
    inline int q(int x,int y){
        int ret=0,lt;
        while(top[x]!=top[y]){
            if(dep[top[x]]<dep[top[y]]){
                lt=x;x=y;y=lt;
            }
            ret=max(ret,ask(1,p[top[x]],p[x]));
            x=f[top[x]];
        }
        if(p[x]>p[y]){
            lt=x;x=y;y=lt;
        }
        if(p[x]<p[y]) ret=max(ret,ask(1,p[x]+1,p[y]));
        return ret;
    }
    inline void Aireen(){
        scanf("%d",&n);
        for(int i=1,j,k,l;i<n;++i){
            scanf("%d%d%d",&j,&k,&l);
            addedge(j,k,l,i);addedge(k,j,l,i);
        }
        dep[1]=1;dfs1(1);
        cnt=0;dfs2(1,1);
        build(1,1,n);
        while(true){
            scanf("%s",c);
            if(c[1]=='t') return;
            if(c[1]=='h'){
                scanf("%d%d",&u,&x);
                cover(1,p[b[u]],p[b[u]],x);
            }
            else if(c[1]=='o'){
                scanf("%d%d%d",&u,&v,&x);
                cov(u,v,x);
            }
            else if(c[1]=='d'){
                scanf("%d%d%d",&u,&v,&x);
                ad(u,v,x);
            }
            else if(c[1]=='a'){
                scanf("%d%d",&u,&v);
                printf("%d
    ",q(u,v));
            }
        }
    }
    int main(){
        freopen("moon.in","r",stdin);
        freopen("moon.out","w",stdout);
        Aireen();
        fclose(stdin);
        fclose(stdout);
        return 0;
    }
  • 相关阅读:
    广佛肇城轨年内通车 佛山西站预计2017年中通车
    MTK+Android编译
    电量检测芯片BQ27510使用心得
    放大电路的分析方法
    放大电路的分析方法
    模拟电子放大电路分析
    模拟电子技术二极管
    unsigned 整型实现无溢出运算
    hdu 5317 RGCDQ(前缀和)
    CodeForces 429 B Working out(递推dp)
  • 原文地址:https://www.cnblogs.com/AireenYe/p/6229109.html
Copyright © 2020-2023  润新知