• 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

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

    树链剖分+线段树维护 区间max,区间覆盖标记,区间增加量标记

    #include<cstdio>
    char buf[10000005],*ptr=buf-1;
    inline int input(){
        int x=0,c=*++ptr,f=1;
        while(c>57||c<48){if(c=='-')f=-1;c=*++ptr;}
        while(c>47&&c<58)x=x*10+c-48,c=*++ptr;
        return x*f;
    }
    inline int getop(){
        int c=*++ptr;
        while(c<33)c=*++ptr;
        return *++ptr;
    }
    const int N=100050;
    int mx[N*2],a[N*2],lc[N*2],rc[N*2],p=0,n;
    bool cov[N*2];
    int es[N*2],enx[N*2],ev[N*2],e0[N],v0[N],ep=2;
    int l,r,ans;
    int fa[N],dep[N],son[N],sz[N],top[N],v[N],id[N],ei[N][2],idr[N],idp=1;
    inline int max(int a,int b){return a>b?a:b;}
    void dwn(int w){
        if(a[w]){
            if(lc[w]){
                a[lc[w]]+=a[w];
                mx[lc[w]]+=a[w];
                a[rc[w]]+=a[w];
                mx[rc[w]]+=a[w];
            }
            a[w]=0;
        }
        if(cov[w]){
            if(lc[w]){
                cov[lc[w]]=cov[rc[w]]=1;
                mx[lc[w]]=mx[rc[w]]=mx[w];
            }
            cov[w]=0;
        }
    }
    inline void up(int w){
        mx[w]=max(mx[lc[w]],mx[rc[w]]);
    }
    int build(int L,int R){
        int u=++p;
        if(L==R){
            mx[u]=v0[idr[L]];
            return u;
        }
        int M=L+R>>1;
        lc[u]=build(L,M);
        rc[u]=build(M+1,R);
        up(u);
        return u;
    }
    void getmax(int w,int L,int R){
        if(l<=L&&R<=r){
            ans=max(ans,mx[w]);
            return;
        }
        dwn(w);
        int M=L+R>>1;
        if(l<=M)getmax(lc[w],L,M);
        if(r>M)getmax(rc[w],M+1,R);
    }
    void chg(int w,int L,int R){
        if(l<=L&&R<=r){
            a[w]=0;
            cov[w]=1;
            mx[w]=ans;
            return;
        }
        dwn(w);
        int M=L+R>>1;
        if(l<=M)chg(lc[w],L,M);
        if(r>M)chg(rc[w],M+1,R);
        up(w);
    }
    void inc(int w,int L,int R){
        if(l<=L&&R<=r){
            if(!cov[w])a[w]+=ans;
            mx[w]+=ans;
            return;
        }
        dwn(w);
        int M=L+R>>1;
        if(l<=M)inc(lc[w],L,M);
        if(r>M)inc(rc[w],M+1,R);
        up(w);
    }
    void f1(int w,int pa){
        fa[w]=pa;
        dep[w]=dep[pa]+1;
        sz[w]=1;
        for(int i=e0[w];i;i=enx[i]){
            int u=es[i];
            if(u==pa)continue;
            v0[u]=ev[i];
            f1(u,w);
            sz[w]+=sz[u];
            if(sz[u]>sz[son[w]])son[w]=u;
        }
    }
    void f2(int w,int tp){
        top[w]=tp;
        idr[id[w]=idp++]=w;
        if(son[w])f2(son[w],tp);
        for(int i=e0[w];i;i=enx[i]){
            int u=es[i];
            if(u!=fa[w]&&u!=son[w])f2(u,u);
        }
    }
    void qmax(int x,int y){
        ans=0;
        int a=top[x],b=top[y],c;
        while(a!=b){
            if(dep[a]<dep[b])c=a,a=b,b=c,c=x,x=y,y=c;
            l=id[a];r=id[x];
            getmax(1,1,n);
            x=fa[a];a=top[x];
        }
        if(dep[x]<dep[y])l=id[x]+1,r=id[y];
        else l=id[y]+1,r=id[x];
        if(l<=r)getmax(1,1,n);
        printf("%d
    ",ans);
    }
    void add(int x,int y){
        int a=top[x],b=top[y],c;
        while(a!=b){
            if(dep[a]<dep[b])c=a,a=b,b=c,c=x,x=y,y=c;
            l=id[a];r=id[x];
            inc(1,1,n);
            x=fa[a];a=top[x];
        }
        if(dep[x]<dep[y])l=id[x]+1,r=id[y];
        else l=id[y]+1,r=id[x];
        if(l<=r)inc(1,1,n);
    }
    void change(int x,int y){
        int a=top[x],b=top[y],c;
        while(a!=b){
            if(dep[a]<dep[b])c=a,a=b,b=c,c=x,x=y,y=c;
            l=id[a];r=id[x];
            chg(1,1,n);
            x=fa[a];a=top[x];
        }
        if(dep[x]<dep[y])l=id[x]+1,r=id[y];
        else l=id[y]+1,r=id[x];
        if(l<=r)chg(1,1,n);
    }
    int main(){
        fread(buf,1,10000000,stdin);
        n=input();
        for(int i=1;i<n;i++){
            int a=input(),b=input(),c=input();
            es[ep]=b;enx[ep]=e0[a];ev[ep]=c;e0[a]=ep++;
            es[ep]=a;enx[ep]=e0[b];ev[ep]=c;e0[b]=ep++;
            ei[i][0]=a;
            ei[i][1]=b;
        }
        f1(1,0);f2(1,1);build(1,n);
        while(1){
            int op=getop();
            if(op=='t')break;
            if(op=='a'){
                int a=input(),b=input();
                qmax(a,b);
            }else if(op=='h'){
                int a=input(),b=input();
                l=r=(dep[ei[a][0]]>dep[ei[a][1]]?id[ei[a][0]]:id[ei[a][1]]);
                ans=b;
                chg(1,1,n);
            }else if(op=='d'){
                int a=input(),b=input(),c=input();
                ans=c;
                add(a,b);
            }else{
                int a=input(),b=input(),c=input();
                ans=c;
                change(a,b);
            }
        }
        return 0;
    }
  • 相关阅读:
    Java中数据类型的分类
    PL/SQL Developer工具
    Oracle数据库SQL语句的分类
    Oracle数据库控制台常用命令
    关于C#中泛型类型参数约束(where T : class)
    C#动态操作DataTable(新增行、列、查询行、列等)
    ADO.NET 全面整理
    区块链入门教程
    排序算法汇总
    常用SQL
  • 原文地址:https://www.cnblogs.com/ccz181078/p/5515072.html
Copyright © 2020-2023  润新知