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));
}
}
}