zoukankan      html  css  js  c++  java
  • 【BZOJ1984】月下“毛景树” 树链剖分+线段树

    【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行,每行三个正整数Ui,Vi和Wi,第i+1行描述第i条树枝。表示第i条树枝连接节点Ui和节点Vi,树枝上有Wi个毛毛果。 接下来是操作和询问,以“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

    【Data Range】
    1<=N<=100,000,操作+询问数目不超过100,000。
    保证在任意时刻,所有树枝上毛毛果的个数都不会超过10^9个。

    题解:树剖+线段树裸题,不过注意是边权,把边权转换成点权,去掉最上面的点即可。还要注意一下cover和add两个标签的处理顺序。

    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    #define lson x<<1
    #define rson x<<1|1
    using namespace std;
    const int maxn=150010;
    int n,cnt,tot;
    int s[maxn<<2],p[maxn],tc[maxn<<2],ts[maxn<<2];
    int to[maxn<<1],next[maxn<<1],val[maxn<<1],v[maxn],u[maxn],fa[maxn],head[maxn];
    int deep[maxn],size[maxn],son[maxn],top[maxn];
    char str[10];
    int readin()
    {
        int ret=0,sig=1;    char gc;
        while(gc<'0'||gc>'9')    sig=(gc=='-')?-1:1,gc=getchar();
        while(gc>='0'&&gc<='9')    ret=ret*10+gc-'0',gc=getchar();
        return ret*sig;
    }
    void add(int a,int b,int c)
    {
        to[cnt]=b;
        val[cnt]=c;
        next[cnt]=head[a];
        head[a]=cnt++;
    }
    void dfs1(int x)
    {
        size[x]=1;
        for(int i=head[x];i!=-1;i=next[i])
        {
            if(to[i]!=fa[x])
            {
                fa[to[i]]=x;
                deep[to[i]]=deep[x]+1;
                u[to[i]]=val[i];
                dfs1(to[i]);
                size[x]+=size[to[i]];
                if(size[to[i]]>size[son[x]])    son[x]=to[i];
            }
        }
    }
    void dfs2(int x,int tp)
    {
        top[x]=tp;
        p[x]=++tot;
        v[p[x]]=u[x];
        if(son[x])    dfs2(son[x],tp);
        for(int i=head[x];i!=-1;i=next[i])
            if(to[i]!=son[x]&&to[i]!=fa[x])
                dfs2(to[i],to[i]);
    }
    void pushup(int x)
    {
        s[x]=max(s[lson],s[rson]);
    }
    void pushdown(int x)
    {
        if(tc[x]!=-1)    //注意顺序
        {
            s[lson]=s[rson]=tc[lson]=tc[rson]=tc[x];
            ts[lson]=ts[rson]=0;
            tc[x]=-1;
        }
        if(ts[x])
        {
            s[lson]+=ts[x],s[rson]+=ts[x],ts[lson]+=ts[x],ts[rson]+=ts[x];
            ts[x]=0;
        }
    }
    void build(int l,int r,int x)
    {
        if(l==r)
        {
            s[x]=v[l];
            return ;
        }
        int mid=l+r>>1;
        build(l,mid,lson),build(mid+1,r,rson);
        pushup(x);
    }
    int query(int l,int r,int x,int a,int b)
    {
        pushdown(x);
        if(a<=l&&r<=b)    return s[x];
        int mid=l+r>>1;
        if(b<=mid)    return query(l,mid,lson,a,b);
        if(a>mid)    return query(mid+1,r,rson,a,b);
        return max(query(l,mid,lson,a,b),query(mid+1,r,rson,a,b));
    }
    void upcover(int l,int r,int x,int a,int b,int c)
    {
        pushdown(x);
        if(a<=l&&r<=b)
        {
            s[x]=tc[x]=c;
            return ;
        }
        int mid=l+r>>1;
        if(b<=mid)    upcover(l,mid,lson,a,b,c);
        else if(a>mid)    upcover(mid+1,r,rson,a,b,c);
        else    upcover(l,mid,lson,a,b,c),upcover(mid+1,r,rson,a,b,c);
        pushup(x);
    }
    void updata(int l,int r,int x,int y,int c)
    {
        if(l==r)
        {
            s[x]=c;
            return ;
        }
        pushdown(x);
        int mid=l+r>>1;
        if(y<=mid)    updata(l,mid,lson,y,c);
        else    updata(mid+1,r,rson,y,c);
        pushup(x);
    }
    void upadd(int l,int r,int x,int a,int b,int c)
    {
        pushdown(x);
        if(a<=l&&r<=b)
        {
            s[x]+=c,ts[x]+=c;
            return ;
        }
        int mid=l+r>>1;
        if(b<=mid)    upadd(l,mid,lson,a,b,c);
        else if(a>mid)    upadd(mid+1,r,rson,a,b,c);
        else upadd(l,mid,lson,a,b,c),upadd(mid+1,r,rson,a,b,c);
        pushup(x);
    }
    void getmax()
    {
        int x=readin(),y=readin(),ans=0;
        while(top[x]!=top[y])
        {
            if(deep[top[x]]<deep[top[y]])    swap(x,y);
            ans=max(ans,query(1,n,1,p[top[x]],p[x]));
            x=fa[top[x]];
        }
        if(deep[x]>deep[y])    swap(x,y);
        if(x!=y)    ans=max(ans,query(1,n,1,p[x]+1,p[y]));    //p[x]要+1,取下面那一个点
        printf("%d
    ",ans);
    }
    void Cover()
    {
        int x=readin(),y=readin(),z=readin();
        while(top[x]!=top[y])
        {
            if(deep[top[x]]<deep[top[y]])    swap(x,y);
            upcover(1,n,1,p[top[x]],p[x],z);
            x=fa[top[x]];
        }
        if(deep[x]>deep[y])    swap(x,y);
        if(x!=y)    upcover(1,n,1,p[x]+1,p[y],z);
    }
    void Change()
    {
        int x=readin(),y=readin();
        updata(1,n,1,max(p[to[x*2-2]],p[to[x*2-1]]),y);
    }
    void Add()
    {
        int x=readin(),y=readin(),z=readin();
        while(top[x]!=top[y])
        {
            if(deep[top[x]]<deep[top[y]])    swap(x,y);
            upadd(1,n,1,p[top[x]],p[x],z);
            x=fa[top[x]];
        }
        if(deep[x]>deep[y])    swap(x,y);
        if(x!=y)    upadd(1,n,1,p[x]+1,p[y],z);
    }
    int main()
    {
        n=readin();
        int i,a,b,c;
        memset(head,-1,sizeof(head));
        memset(tc,-1,sizeof(tc));
        for(i=1;i<n;i++)
        {
            a=readin(),b=readin(),c=readin();
            add(a,b,c),add(b,a,c);
        }
        deep[1]=1;
        dfs1(1);
        dfs2(1,1);
        build(1,n,1);
        while(scanf("%s",str))
        {
            switch(str[1])
            {
                case 'a':getmax();    break;
                case 'o':Cover();    break;
                case 'd':Add();    break;
                case 'h':Change();    break;
                case 't':return 0;
            }
        }
    }
  • 相关阅读:
    EOJ2032 判断两个数是否相等
    EOJ2529 强大的lwc
    EOJ 1199 Anagram
    EOJ2530 数字之和
    EOJ2941 在线投票系统
    EOJ2124 Seamild的电梯
    EOJ 1027 邮资的问题
    通过js导入js,通过js导入css
    无意间在我系统中发现的一张图~~~~~
    css系列看过之后让我~~~
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/6184440.html
Copyright © 2011-2022 走看看