zoukankan      html  css  js  c++  java
  • [BZOJ]1984: 月下“毛景树”

    题目大意:树上一系列沙茶操作

    Max x--y 树上x--y之间边的最大权值

    Cover x--y w.树上x--y之前边的权值都变为w

    Add x--y w 树上x--y之间边权都加w

    Change x w把第x条边权值改为w

    题解:树链剖分

    权值是边的不是点的,由于树上每个点只有一个爸爸,所以让每个点记录

    它到它爸爸这条边的权值,也就是边的权值降到深度大的端点。

    然后再注意的就是双标记下传。

    Cover操作一个标记,Add操作一个标记..ps:第一遍写到一半发现标记

    不能一起下传..有先后的。

    在Cover操作时,将Add标记清0,pushdown时,将儿子的Add标记也清0

    Add操作时,Cover标记不用清0。

    因为区间加一个值然后全部变为另一个值,区间加这个操作没什么用。

    ps:修改忘记pushup,WA了...有毒...

    代码:差点破200..

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define maxn 300009
    using namespace std;
    
    int n,m,cnt,sumedge;
    int size[maxn],dad[maxn],deep[maxn],top[maxn],head[maxn];
    int tpos[maxn],re[maxn],fe[maxn],st[maxn],ed[maxn];
    char s[10];
    
    struct Tree{
        int l,r,mx,adc,cvs;
    }tr[maxn<<2];
    
    struct Edge{
        int x,y,z,nxt;
        Edge(int x=0,int y=0,int z=0,int nxt=0):
            x(x),y(y),z(z),nxt(nxt){}
    }edge[maxn<<1];
    
    void add(int x,int y,int z){
        edge[++sumedge]=Edge(x,y,z,head[x]);
        head[x]=sumedge;
    }
    
    void dfs(int x){
        size[x]=1;deep[x]=deep[dad[x]]+1;
        for(int i=head[x];i;i=edge[i].nxt){
            int v=edge[i].y;
            if(v==dad[x])continue;
            dad[v]=x;fe[v]=edge[i].z;dfs(v);
            size[x]+=size[v];
        }
    }
    
    void dfs_(int x){
        int s=0;
        if(!top[x])top[x]=x;
        tpos[x]=++cnt;re[cnt]=x;
        for(int i=head[x];i;i=edge[i].nxt){
            int v=edge[i].y;
            if(v!=dad[x]&&size[v]>size[s])s=v;
        }
        if(s){
            top[s]=top[x];
            dfs_(s);
        }
        for(int i=head[x];i;i=edge[i].nxt){
            int v=edge[i].y;
            if(v!=dad[x]&&v!=s)dfs_(v);
        }
    }
    
    void pushup(int rt){
        tr[rt].mx=max(tr[rt<<1].mx,tr[rt<<1|1].mx);
        return;
    }
    
    void pushdown(int rt){
        if(tr[rt].cvs!=-1){
            tr[rt<<1].mx=tr[rt<<1|1].mx=tr[rt].cvs;
            tr[rt<<1].adc=tr[rt<<1|1].adc=0;
            tr[rt<<1].cvs=tr[rt<<1|1].cvs=tr[rt].cvs;
            tr[rt].cvs=-1;
        }
        if(tr[rt].adc){
            tr[rt<<1].mx+=tr[rt].adc;tr[rt<<1|1].mx+=tr[rt].adc;
            tr[rt<<1].adc+=tr[rt].adc;tr[rt<<1|1].adc+=tr[rt].adc;
            tr[rt].adc=0;
        }
    }
    
    void build(int rt,int l,int r){
        tr[rt].l=l;tr[rt].r=r;tr[rt].cvs=-1;
        if(l==r){
            tr[rt].mx=fe[re[l]];
            return;
        }
        int mid=(l+r)>>1;
        build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);
        pushup(rt);
    }
    //-----------------------------------------------------
    void change_Node(int rt,int l,int r,int p,int w){
        if(l==r){
            tr[rt].mx=w;
            return;
        }
        pushdown(rt);
        int mid=(l+r)>>1;
        if(p<=mid)change_Node(rt<<1,l,mid,p,w);
        if(p>mid)change_Node(rt<<1|1,mid+1,r,p,w);
        pushup(rt);
    }
    
    void change_node(int k,int w){
        int p,x,y;
        x=st[k];y=ed[k];p=dad[x]==y?x:y;
        change_Node(1,1,n,tpos[p],w);
    }
    //--------------------------------------------------------
    void change_Cover(int rt,int l,int r,int ql,int qr,int w){
        if(l>=ql&&r<=qr){
            tr[rt].mx=w;tr[rt].cvs=w;tr[rt].adc=0;
            return;
        }
        pushdown(rt);
        int mid=(l+r)>>1;
        if(ql<=mid)change_Cover(rt<<1,l,mid,ql,qr,w);
        if(qr>mid)change_Cover(rt<<1|1,mid+1,r,ql,qr,w);
        pushup(rt);
    }
    
    void change_cover(int x,int y,int w){
        for(;top[x]!=top[y];){
            if(deep[top[x]]>deep[top[y]])swap(x,y);
            change_Cover(1,1,n,tpos[top[y]],tpos[y],w);
            y=dad[top[y]];
        }
        if(deep[x]>deep[y])swap(x,y);
        change_Cover(1,1,n,tpos[x]+1,tpos[y],w);
    }
    //---------------------------------------------------------
    void change_Add(int rt,int l,int r,int ql,int qr,int w){
        if(l>=ql&&r<=qr){
            tr[rt].mx+=w;tr[rt].adc+=w;
            return;
        }
        pushdown(rt);
        int mid=(l+r)>>1;
        if(ql<=mid)change_Add(rt<<1,l,mid,ql,qr,w);
        if(qr>mid)change_Add(rt<<1|1,mid+1,r,ql,qr,w);
        pushup(rt);
    }
    
    void change_add(int x,int y,int w){
        for(;top[x]!=top[y];){
            if(deep[top[x]]>deep[top[y]])swap(x,y);
            change_Add(1,1,n,tpos[top[y]],tpos[y],w);
            y=dad[top[y]];
        }
        if(deep[x]>deep[y])swap(x,y);
        change_Add(1,1,n,tpos[x]+1,tpos[y],w);
    }
    //-----------------------------------------------------------
    int query_mx(int rt,int l,int r,int ql,int qr){
        if(l>=ql&&r<=qr){
            return tr[rt].mx;
        }
        pushdown(rt);
        int mid=(l+r)>>1,ret=-1;
        if(ql<=mid)ret=max(ret,query_mx(rt<<1,l,mid,ql,qr));
        if(qr>mid)ret=max(ret,query_mx(rt<<1|1,mid+1,r,ql,qr));
        return ret;
    }
    
    int query(int x,int y){
        int ans=-1;
        for(;top[x]!=top[y];){
            if(deep[top[x]]>deep[top[y]])swap(x,y);
            ans=max(ans,query_mx(1,1,n,tpos[top[y]],tpos[y]));
            y=dad[top[y]];
        }
        if(deep[x]>deep[y])swap(x,y);
        ans=max(ans,query_mx(1,1,n,tpos[x]+1,tpos[y]));
        return ans;
    }
    //------------------------------------------------------------
    int main(){
        scanf("%d",&n);
        for(int i=1;i<n;i++){
            int z;
            scanf("%d%d%d",&st[i],&ed[i],&z);
            add(st[i],ed[i],z);add(ed[i],st[i],z);
        }
        dfs(1);dfs_(1);build(1,1,n);
        while(1){
            int x,y,z;
            scanf("%s",s);
            if(s[0]=='S')break;
            if(s[1]=='h'){
                scanf("%d%d",&x,&z);                                                            
                change_node(x,z);
            }else if(s[1]=='o'){
                scanf("%d%d%d",&x,&y,&z);
                change_cover(x,y,z);
            }else if(s[1]=='d'){
                scanf("%d%d%d",&x,&y,&z);
                change_add(x,y,z);
            }else if(s[2]=='x'){
                scanf("%d%d",&x,&y);
                printf("%d
    ",query(x,y));
            }
        }
        return 0;
    }
    AC
  • 相关阅读:
    智能实验室-杀马(Defendio) 4.12.0.800
    智能实验室-结构化存储浏览器(SSExplorer) 1.7.0.170
    智能实验室-全能优化(Guardio) 4.94.0.830
    智能实验室-全能优化(Guardio) 4.9.0.790
    IT餐馆—第二十二回 控件
    当DiscuzNT遇上了Loadrunner(中)
    在Discuz!NT中进行缓存分层(本地缓存+memcached)
    介绍三个Silverlight 在线编辑器控件
    玩玩负载均衡在window与linux下配置nginx
    IT餐馆—第十八回 祭奠
  • 原文地址:https://www.cnblogs.com/zzyh/p/7703904.html
Copyright © 2011-2022 走看看