poj 3237 Tree

给一棵边权树,再给三个操作。第一个把一条边权改为v,第二个将一条链的值取反,第三个求一条链的最大值。

考虑用线段树维护连续区间的最大最小值。区间取反打lazy标记,如果lazy是奇数就取反再把最大最小值交换下放,否则不管,单点更新和区间查询很简单。

最后用树剖更新区间。把边权映射到点权即可。

 

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define Lson l,mid,rt<<1
#define Rson mid+1,r,rt<<1|1
using namespace std;
const int M = 1e5+7;
typedef long long ll;
int _,n,pp;
int cnt,tot,head[M],p[M];
int sz[M],son[M],dep[M],f[M],top[M],rnk[M],id[M];
ll a[M];
char s[10];
struct edge
{
    int v,next;
    ll w;
}e[M<<1];
struct node
{
    ll mx,mn;int lazy;    
}tree[M<<2];
void init(){
    tot=cnt=0;memset(head,-1,sizeof(head));
}
void add(int u,int v,ll w){
    e[++cnt].v=v;e[cnt].w=w;e[cnt].next=head[u];
    head[u]=cnt;
}
void fsd(int u,int fa){
    for(int i=head[u];~i;i=e[i].next){
        int v=e[i].v;ll w=e[i].w;
        if(v==fa) continue;
        a[v]=w;p[(i-1)/2+1]=v;
        fsd(v,u);
    }
    return ;
}
void dfs(int u,int fa,int d){
    sz[u]=1;f[u]=fa;son[u]=-1;dep[u]=d;
    for(int i=head[u];~i;i=e[i].next){
        int v=e[i].v;
        if(v==fa) continue;
        dfs(v,u,d+1);
        sz[u]+=sz[v];
        if(son[u]==-1||sz[v]>sz[son[u]]) son[u]=v;
    }
    return ;
}
void dfs1(int u,int t){
    id[u]=++tot;
    rnk[tot]=u;
    top[u]=t;
    if(son[u]==-1) return;
    dfs1(son[u],t);
    for(int i=head[u];~i;i=e[i].next){
        int v=e[i].v;
        if(v==f[u]||v==son[u]) continue;
        dfs1(v,v);
    }
    return ;
}
void Pushup(int rt){
    tree[rt].mx=max(tree[rt<<1].mx,tree[rt<<1|1].mx);
    tree[rt].mn=min(tree[rt<<1].mn,tree[rt<<1|1].mn);
}
void Pushdown(int rt){
    if(tree[rt].lazy){
        int v=tree[rt].lazy;
        tree[rt].lazy=0;
        if(v%2==0){
            return ;
        }
        tree[rt<<1].mn*=-1;tree[rt<<1].mx*=-1;
        tree[rt<<1|1].mn*=-1;tree[rt<<1|1].mx*=-1;
        swap(tree[rt<<1].mn,tree[rt<<1].mx);
        swap(tree[rt<<1|1].mx,tree[rt<<1|1].mn);
        tree[rt<<1].lazy+=v;tree[rt<<1|1].lazy+=v;
    }
}
void build(int l,int r,int rt){
    tree[rt].mx=-1e15,tree[rt].mn=1e15;tree[rt].lazy=0;
    if(l==r){
        tree[rt].mx=tree[rt].mn=a[rnk[l]];
        return ;
    }
    int mid=(l+r)>>1;
    build(Lson);
    build(Rson);
    Pushup(rt);
}
void update(int L,int R,int l,int r,int rt){
    if(L<=l&&r<=R){
        tree[rt].lazy++;
        tree[rt].mx*=-1;tree[rt].mn*=-1;
        swap(tree[rt].mx,tree[rt].mn);
        return ;
    }
    Pushdown(rt);
    int mid=(l+r)>>1;
    if(L<=mid) update(L,R,Lson);
    if(R>mid) update(L,R,Rson);
    Pushup(rt);
    return ;
}
void change(int l,int r,int rt,ll v){
    if(l==r){
        tree[rt].mx=tree[rt].mn=v;
        return ;
    }
    Pushdown(rt);
    int mid=(l+r)>>1;
    if(pp<=mid) change(Lson,v);
    else change(Rson,v);
    Pushup(rt);
}
ll query(int L,int R,int l,int r,int rt){
    if(L<=l&&r<=R){
        return tree[rt].mx;
    }
    Pushdown(rt);
    int mid=(l+r)>>1;ll res=-1e15;
    if(L<=mid) res=max(res,query(L,R,Lson));
    if(R>mid) res=max(res,query(L,R,Rson));
    return res; 
}
void updates(int x,int y){
    int fx=top[x],fy=top[y];
    while(fx!=fy){
        if(dep[fx]>dep[fy]){
            update(id[fx],id[x],1,n,1);
            x=f[fx],fx=top[x];
        }
        else{
            update(id[fy],id[y],1,n,1);
            y=f[fy],fy=top[y];
        }
    }
    if(x==y) return ;
    if(dep[x]<dep[y])
        update(id[son[x]],id[y],1,n,1);
    else
        update(id[son[y]],id[x],1,n,1);
}
ll sum(int x,int y){
    int fx=top[x],fy=top[y];ll res=-1e15;
    while(fx!=fy){
        if(dep[fx]>dep[fy]){
            res=max(res,query(id[fx],id[x],1,n,1));
            x=f[fx],fx=top[x];
        }
        else{
            res=max(res,query(id[fy],id[y],1,n,1));
            y=f[fy],fy=top[y];
        }
    }
    if(x==y) return res;
    if(dep[x]<dep[y])
        res=max(res,query(id[son[x]],id[y],1,n,1));
    else
        res=max(res,query(id[son[y]],id[x],1,n,1));
    return res;
}
int main(){
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    scanf("%d",&_);
    while(_--){
        init();
        scanf("%d",&n);
        for(int i=1;i<n;i++){
            int u,v;ll w;
            scanf("%d%d%lld",&u,&v,&w);
            add(u,v,w);add(v,u,w);
        }
        fsd(1,-1);a[1]=0ll;
        dfs(1,-1,1);
        dfs1(1,1);
        build(1,n,1);
        while(1){
            scanf("%s",s);
            if(s[0]=='D') break;
            if(s[0]=='C'){
                int a;ll b;
                scanf("%d%lld",&a,&b);pp=id[p[a]];
                change(1,n,1,b);
            }
            if(s[0]=='N'){
                int a,b;
                scanf("%d%d",&a,&b);
                updates(a,b);
            }
            if(s[0]=='Q'){
                int a,b;
                scanf("%d%d",&a,&b);
                printf("%lld\n",sum(a,b));
            }
        }
    }
    return 0;
}
View Code

 

posted @ 2018-08-27 21:58  LMissher  阅读(142)  评论(0编辑  收藏  举报