版权声明:蒟蒻Blog随意转载 https://blog.csdn.net/a1799342217/article/details/81812833
树链剖分 (线段树动态开点)
学了发线段树动态开点。
其实动态开点就是先不建树,每次修改的时候再往下建。这时左右儿子是编号的而不是原来的 和 。可以发现每次新建的节点数为 ,那么总空间复杂度就是 的。
这道题的话对每种颜色都开一个线段树。然后树剖上去+动态开点就好了。
代码:
#include<cctype>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100005
#define F inline
using namespace std;
struct edge{ int nxt,to; }ed[N<<1];
struct tree{ int ls,rs,l,r,mx,s; }t[N<<6];
int n,m,k,ti,nd,h[N],w[N],c[N],rt[N],sz[N],to[N],tp[N],fa[N],dep[N],in[N];
F char readc(){
static char buf[100000],*l=buf,*r=buf;
if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);
return l==r?EOF:*l++;
}
F int _read(){
int x=0; char ch=readc();
while (!isdigit(ch)&&!isupper(ch)) ch=readc();
if (isupper(ch)) return ch=readc();
while (isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=readc();
return x;
}
F void writec(int x){ if (x>9) writec(x/10); putchar(x%10+48); }
F void _write(int x){ writec(x),puts(""); }
#define add(x,y) ed[++k]=(edge){h[x],y},h[x]=k
void dfs1(int x){
dep[x]=dep[fa[x]]+1,sz[x]=1;
for (int i=h[x],v;i;i=ed[i].nxt)
if ((v=ed[i].to)!=fa[x]){
fa[v]=x,dfs1(v),sz[x]+=sz[v];
if (sz[to[x]]<sz[v]) to[x]=v;
}
}
void dfs2(int x){
in[x]=++ti;
if (to[x]) tp[to[x]]=tp[x],dfs2(to[x]);
for (int i=h[x],v;i;i=ed[i].nxt)
if ((v=ed[i].to)!=fa[x]&&v!=to[x])
tp[v]=v,dfs2(v);
}
#define max(x,y) ((x)>(y)?(x):(y))
void mdfy(int &x,int l,int r,int p,int w){
if (!x) x=++nd; t[x].l=l,t[x].r=r; int mid;
if (l==r) return void(t[x].mx=t[x].s=w);
if ((mid=l+r>>1)>=p) mdfy(t[x].ls,l,mid,p,w);
else mdfy(t[x].rs,mid+1,r,p,w);
t[x].s=t[t[x].ls].s+t[t[x].rs].s;
t[x].mx=max(t[t[x].ls].mx,t[t[x].rs].mx);
}
tree srch(int x,int l,int r){
tree s,ls,rs; s.mx=s.s=0;
if (t[x].l>r||t[x].r<l) return s;
if (t[x].l>=l&&t[x].r<=r) return t[x];
ls=srch(t[x].ls,l,r),rs=srch(t[x].rs,l,r);
return s.s=ls.s+rs.s,s.mx=max(ls.mx,rs.mx),s;
}
tree find(int x,int y){
tree ans,p; ans.s=ans.mx=0; int cc=c[x];
while (tp[x]!=tp[y]){
if (dep[tp[x]]<dep[tp[y]]) swap(x,y);
p=srch(rt[cc],in[tp[x]],in[x]);
ans.s+=p.s,ans.mx=max(ans.mx,p.mx),x=fa[tp[x]];
}
if (dep[x]<dep[y]) swap(x,y);
p=srch(rt[cc],in[y],in[x]);
return ans.s+=p.s,ans.mx=max(ans.mx,p.mx),ans;
}
int main(){
n=_read(),m=_read();
for (int i=1;i<=n;i++)
w[i]=_read(),c[i]=_read();
for (int i=1,x,y;i<n;i++)
x=_read(),y=_read(),add(x,y),add(y,x);
dfs1(1),tp[1]=1,dfs2(1);
for (int i=1;i<=n;i++)
mdfy(rt[c[i]],1,n,in[i],w[i]);
while (m--){
int f=_read(),x=_read(),y=_read();
if (f=='C'){
mdfy(rt[c[x]],1,n,in[x],0);
mdfy(rt[c[x]=y],1,n,in[x],w[x]);
}
else if (f=='W')
mdfy(rt[c[x]],1,n,in[x],w[x]=y);
else _write(f=='S'?find(x,y).s:find(x,y).mx);
}
return 0;
}