P3313 [SDOI2014]旅行

题目

P3313 [SDOI2014]旅行

码农题╮(╯▽╰)╭

为了主席树来的,结果发现是个假标签,又折腾了一个多小时,上一次做树剖题是五个月前了
果然还是不熟犯了个**错误(分链处理时往上爬是跳到链头的父亲结点)

想思路(10min)+打代码(20min)+调代码(40min++)

做法

树剖+线段树

对于每种信仰建线段树,然后线段树下标为\(dfs\)序(标准树剖,不需要再解释了吧)

然后每次改信仰就从清空原信仰树,添加到新信仰树
改数值就直接在信仰树上重新复制就好了

My complete code

想卡下常还莫名其妙WA了,吸完氧1s左右

// luogu-judger-enable-o2
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<set>
using namespace std;
typedef int LL;
const LL maxn=4000000;
void Change(LL &now,LL l,LL r,LL c,LL val);
inline LL Read(){
    LL x(0),f(1);char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-'0',c=getchar();
    return x*f;
}
LL n,m,num,tot,nod;
LL top[maxn],fa[maxn],dep[maxn],bson[maxn],size[maxn],zong[maxn],val[maxn],head[maxn],dfn[maxn],root[maxn];
struct node{
    LL to,next;
}dis[maxn];
inline void Add(LL u,LL v){
    dis[++num]=(node){v,head[u]}; head[u]=num;
}
void Dfs1(LL u){
    size[u]=1;
    LL M(0);
    for(LL i=head[u];i;i=dis[i].next){
        LL v(dis[i].to);
        if(v==fa[u])continue;
        fa[v]=u;
        dep[v]=dep[u]+1;
        Dfs1(v);
        size[u]+=size[v];
        if(size[v]>M){
            M=size[v];
            bson[u]=v;
        }
    }
}//
void Dfs2(LL u,LL f){
    dfn[u]=++tot; 
    Change(root[zong[u]],1,n,dfn[u],val[u]);
    top[u]=f;
    if(bson[u])
        Dfs2(bson[u],f);//
    for(LL i=head[u];i;i=dis[i].next){
        LL v(dis[i].to);
        if(v==fa[u]||v==bson[u])continue;
        Dfs2(v,v);
    }
}
struct Tree{
    LL sum,max,son[2];
}T[maxn];
inline void Update(LL now){
    LL son0(T[now].son[0]),son1(T[now].son[1]);
    T[now].max=T[now].sum=0;
    if(son0){
        T[now].sum=T[son0].sum;
        T[now].max=T[son0].max;
    }
    if(son1){
        T[now].sum+=T[son1].sum;
        T[now].max=max(T[now].max,T[son1].max);
    }
}
void Change(LL &now,LL l,LL r,LL c,LL zhi){
    if(!now) now=++nod;
    if(l==r){
        T[now].sum=T[now].max=zhi;
        return;
    }
    LL mid(l+r>>1);
    if(c<=mid)
        Change(T[now].son[0],l,mid,c,zhi);
    else
        Change(T[now].son[1],mid+1,r,c,zhi);
    Update(now);
}
LL QueryS(LL now,LL l,LL r,LL lt,LL rt){
    if(now==0) return 0;
    if(lt<=l&&rt>=r)
        return T[now].sum;
    LL mid(l+r>>1),ret(0);
    if(lt<=mid)
        ret+=QueryS(T[now].son[0],l,mid,lt,rt);
    if(rt>mid)
        ret+=QueryS(T[now].son[1],mid+1,r,lt,rt);
    return ret;
}
inline LL SolveS(LL x,LL y){
    LL fx=top[x],fy=top[y],ans(0),c=zong[x];
    while(fx!=fy){
        if(dep[fx]>=dep[fy]){
            ans+=QueryS(root[c],1,n,dfn[fx],dfn[x]);
            x=fa[fx];
        }else{
            ans+=QueryS(root[c],1,n,dfn[fy],dfn[y]);
            y=fa[fy];
        }
        fx=top[x], fy=top[y];
    }
    if(dfn[x]<=dfn[y])
        ans+=QueryS(root[c],1,n,dfn[x],dfn[y]);
    else
        ans+=QueryS(root[c],1,n,dfn[y],dfn[x]);
    return ans;
}
LL QueryM(LL now,LL l,LL r,LL lt,LL rt){
    if(!now) return 0;
    if(lt<=l&&rt>=r)
        return T[now].max;
    LL mid(l+r>>1),ret(0);
    if(lt<=mid)
        ret=max(ret,QueryM(T[now].son[0],l,mid,lt,rt));
    if(rt>mid)
        ret=max(ret,QueryM(T[now].son[1],mid+1,r,lt,rt));
    return ret;
}
inline LL SolveM(LL x,LL y){
    LL fx=top[x],fy=top[y],ans(0),c=zong[x];
    while(fx!=fy){
        if(dep[fx]>=dep[fy]){
            ans=max(ans,QueryM(root[c],1,n,dfn[fx],dfn[x]));
            x=fa[fx];
        }else{
            ans=max(ans,QueryM(root[c],1,n,dfn[fy],dfn[y]));
            y=fa[fy];
        }
        fx=top[x], fy=top[y];
    }
    if(dfn[x]<=dfn[y])
        ans=max(ans,QueryM(root[c],1,n,dfn[x],dfn[y]));
    else
        ans=max(ans,QueryM(root[c],1,n,dfn[y],dfn[x]));
    return ans;
}
int main(){
    n=Read(),m=Read();
    for(LL i=1;i<=n;++i){
        val[i]=Read(),zong[i]=Read();
    }
    for(LL i=1;i<n;++i){
        LL u(Read()),v(Read());
        Add(u,v),Add(v,u);
    }
    Dfs1(1); Dfs2(1,1);
    while(m--){
        char s[10];
        scanf(" %s",s);
        if(s[0]=='C'){
            if(s[1]=='C'){
                LL x(Read()),c(Read());
                Change(root[zong[x]],1,n,dfn[x],0);
                zong[x]=c;
                Change(root[zong[x]],1,n,dfn[x],val[x]);
            }else{
                LL x(Read()),w(Read());
                val[x]=w;
                Change(root[zong[x]],1,n,dfn[x],val[x]);
            }
        }else{
            LL x(Read()),y(Read());
            if(s[1]=='S')
                printf("%d\n",SolveS(x,y));
            else
                printf("%d\n",SolveM(x,y));
        }
    }
}
posted @ 2019-01-22 11:25  y2823774827y  阅读(194)  评论(0编辑  收藏  举报