[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\n",query(x,y));
        }
    }
    return 0;
}
AC

 

posted @ 2017-10-21 10:21  ANhour  阅读(242)  评论(0编辑  收藏  举报