造福后人,更好的代码,如果珂朵莉树没过
查看原帖
造福后人,更好的代码,如果珂朵莉树没过
776873
da17_楼主2024/7/3 22:00

由于珂朵莉树的题解代码都不是很适合理解,贴上我的代码

注意询问时如果你是记录了上一次颜色段的结尾颜色,要按dfn倒序算,因为链尾在dfn后面

#include <iostream>
#include <algorithm>
#include <set>
using namespace std;

const int N=1e5+5;
int n,m,a[N],dfn[N],top[N],tim,h[N],dep[N],fa[N],siz[N],son[N],cnt,head[N],lst1,lst2;
struct Edge{ int to,next; }e[N<<1]; void add_edge(int u,int v){ e[++cnt]={v,head[u]},head[u]=cnt; }
struct node{
	int l,r; mutable int v;
	bool operator<(const node &x)const{
		return l<x.l;
	}
}; set<node>s;
#define IT set<node>::iterator
IT split(int x){
	if(x>n) return s.end();
	IT it=--s.upper_bound({x,0,0});
	if(it->l==x) return it;
	int l=it->l,r=it->r,v=it->v;
	s.erase(it),s.insert({l,x-1,v});
	return s.insert({x,r,v}).first;
}
void assign(int l,int r,int v){
	IT itr=split(r+1),itl=split(l);
	s.erase(itl,itr),s.insert({l,r,v});
}
int ask(int l,int r,int &lst,int edlst){ int ret=0; IT itr=split(r+1),itl=split(l);
	for(;itl!=itr&&itr!=s.begin();) --itr,ret+=itr->v!=lst,lst=itr->v; return ret-(lst==edlst);
}
void dfs1(int u){ siz[u]=1;
	for(int i=head[u];i;i=e[i].next){
		int v=e[i].to; if(v==fa[u]) continue;
		dep[v]=dep[u]+1,fa[v]=u,dfs1(v),siz[u]+=siz[v];
		if(siz[v]>siz[son[u]]) son[u]=v;
	}
}
void dfs2(int u,int tp){
	h[dfn[u]=++tim]=u,top[u]=tp;
	if(son[u]) dfs2(son[u],tp);
	for(int i=head[u];i;i=e[i].next){
		int v=e[i].to; if(v==fa[u]||
		v==son[u]) continue; dfs2(v,v);
	}
}
void _set(){
	for(int i=1;i<=n;){ int j=i+1;
		while(j<=n&&a[h[i]]==a[h[j]]) j++;
		s.insert({i,j-1,a[h[i]]}),i=j;
	}
}
void modify(int u,int v,int c){
	while(top[u]^top[v]){
		if(dep[top[u]]<dep[top[v]]) swap(u,v);
		assign(dfn[top[u]],dfn[u],c),u=fa[top[u]];
	} if(dep[u]>dep[v]) swap(u,v); assign(dfn[u],dfn[v],c);
}
int query(int u,int v){ int ret=0; lst1=lst2=0;
	while(top[u]^top[v]){
		if(dep[top[u]]<dep[top[v]]) swap(u,v),swap(lst1,lst2);
		ret+=ask(dfn[top[u]],dfn[u],lst1,0),u=fa[top[u]];
	} if(dep[u]>dep[v]) swap(u,v),swap(lst1,lst2);
	return ret+ask(dfn[u],dfn[v],lst2,lst1);
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		scanf("%d",a+i);
	for(int i=1,u,v;i<n;i++) scanf("%d%d",&u,&v),
		add_edge(u,v),add_edge(v,u);
	dfs1(1),dfs2(1,1),_set(); char op[2];
	for(int i=1,u,v,c;i<=m;i++){
		scanf("%s%d%d",op,&u,&v);
		if(op[0]=='C') scanf("%d",&c),modify(u,v,c);
		else printf("%d\n",query(u,v));
	} return 0;
}
2024/7/3 22:00
加载中...