轻重边

发布时间 2024-01-03 10:47:06作者: zzzzzz2

题面
洛谷P7735
给定一棵\(n\)个点的树,起初所有的边都是轻边。
\(m\)次操作,有两种操作:
1.给一条路径,将与这条路径直接相连的边变成轻边,将这条路径上的边变成重边。
2.给一条路径,问这条路径上有多少条重边。
思路:
这个题有一个非常牛的trick,就是每次一操作后将路径上的点都变成一种新颜色,一条边两端点颜色相同为重边,否则为轻边。然后用树剖线段树维护重边数量和颜色。
代码:

#include<iostream>
using namespace std;
inline int kd(){
	int x=0,f=1;
	char a=getchar();
	while(a<'0'||a>'9'){
		if(a=='-'){
			f=-1;
		}
		a=getchar();
	}
	while(a>='0'&&a<='9'){
		x=x*10+a-'0';
		a=getchar();
	}
	return x*f;
}
int t;
int n,m;
struct node{
	int to;
	int nxt;
}edge[200010];
int head[100010],tot;
inline void addedge(int u,int v){
	edge[++tot].to=v;
	edge[tot].nxt=head[u];
	head[u]=tot;
}
int fa[100010];
int dep[100010];
int sum[100010];
int zs[100010];
int dfn[100010];
int top[100010];
int dui[100010];
int cnt;
inline void dfs1(int u){
	sum[u]=1;
	zs[u]=0;
	for(int i=head[u];i;i=edge[i].nxt){
		int v=edge[i].to;
		if(v==fa[u]){
			continue;
		}
		fa[v]=u;
		dep[v]=dep[u]+1;
		dfs1(v);
		sum[u]+=sum[v];
		if(sum[v]>sum[zs[u]]){
			zs[u]=v;
		}
	}
}
inline void dfs2(int u,int tp){
	top[u]=tp;
	dfn[u]=++cnt;
	dui[cnt]=u;
	if(zs[u]!=0){
		dfs2(zs[u],tp);
	}
	for(int i=head[u];i;i=edge[i].nxt){
		int v=edge[i].to;
		if(v==fa[u]||v==zs[u]){
			continue;
		}
		dfs2(v,v);
	}
}
struct nod{
	int l,r;
	int lz_1;
	int lz_2;
	int sum;
}tree[400010];
inline void build(int i,int l,int r){
	tree[i].l=l;
	tree[i].r=r;
	tree[i].sum=0;
	tree[i].lz_1=-1;
	tree[i].lz_2=0;
	if(l==r){
		return ;
	}
	int mid=(l+r)/2;
	build(i*2,l,mid);
	build(i*2+1,mid+1,r);
}
inline void push_down(int i){
	if(tree[i].lz_1!=-1){
		tree[i*2].lz_1=tree[i].lz_1;
		tree[i*2+1].lz_1=tree[i].lz_1;
		tree[i*2].sum=tree[i].lz_1*(tree[i*2].r-tree[i*2].l+1);
		tree[i*2+1].sum=tree[i].lz_1*(tree[i*2+1].r-tree[i*2+1].l+1);
		tree[i].lz_1=-1;
	}
	if(tree[i].lz_2!=0){
		tree[i*2].lz_2=tree[i].lz_2;
		tree[i*2+1].lz_2=tree[i].lz_2;
		tree[i].lz_2=0;
	}
}
inline void change_1(int i,int l,int r,int p){
	if(tree[i].l>=l&&tree[i].r<=r){
		tree[i].lz_1=p;
		tree[i].sum=p*(tree[i].r-tree[i].l+1);
		return ;
	}
	push_down(i);
	if(tree[i*2].r>=l){
		change_1(i*2,l,r,p);
	}
	if(tree[i*2+1].l<=r){
		change_1(i*2+1,l,r,p);
	}
	tree[i].sum=tree[i*2].sum+tree[i*2+1].sum;
}
int k;
inline void change_2(int i,int l,int r){
	if(tree[i].l>=l&&tree[i].r<=r){
		tree[i].lz_2=k;
		return ;
	}
	push_down(i);
	if(tree[i*2].r>=l){
		change_2(i*2,l,r);
	}
	if(tree[i*2+1].l<=r){
		change_2(i*2+1,l,r);
	}
}
inline int search_1(int i,int l,int r){
	if(tree[i].l>=l&&tree[i].r<=r){
		return tree[i].sum;
	}
	push_down(i);
	int s=0;
	if(tree[i*2].r>=l){
		s+=search_1(i*2,l,r);
	}
	if(tree[i*2+1].l<=r){
		s+=search_1(i*2+1,l,r);
	}
	return s;
}
inline int search_2(int i,int p){
	if(tree[i].l==tree[i].r){
		return tree[i].lz_2;
	}
	push_down(i);
	if(tree[i*2].r>=p){
		return search_2(i*2,p);
	}
	else{
		return search_2(i*2+1,p);
	}
}
inline void lca_1(int u,int v){
	++k;
	while(top[u]!=top[v]){
		if(dep[top[u]]<dep[top[v]]){
			swap(u,v);
		}
		if(zs[u]!=0){
			change_1(1,dfn[zs[u]],dfn[zs[u]],0);
		}
		change_1(1,dfn[top[u]],dfn[u],1);
		change_2(1,dfn[top[u]],dfn[u]);
		u=fa[top[u]];
	}
	if(dep[u]<dep[v]){
		swap(u,v);
	}
	if(zs[u]!=0){
		change_1(1,dfn[zs[u]],dfn[zs[u]],0);
	}
	if(v!=u){
		change_1(1,dfn[v]+1,dfn[u],1);
	}
	change_1(1,dfn[v],dfn[v],0);
	change_2(1,dfn[v],dfn[u]);
}
inline int lca_2(int u,int v){
	int ans=0;
	while(top[u]!=top[v]){
		if(dep[top[u]]<dep[top[v]]){
			swap(u,v);
		}
		if(u!=top[u]){
			ans+=search_1(1,dfn[top[u]]+1,dfn[u]);
		}
		int x=search_2(1,dfn[top[u]]);
		if(x!=0){
			if(x==search_2(1,dfn[fa[top[u]]])){
				ans++;
			}
		}
		u=fa[top[u]];
	}
	if(dep[u]<dep[v]){
		swap(u,v);
	}
	if(v!=u){
		ans+=search_1(1,dfn[v]+1,dfn[u]);
	}
	return ans;
}
int main(){
	cin>>t;
	while(t--){
		cin>>n>>m;
		for(int i=1;i<=n;i++){
			head[i]=0;
			fa[i]=0;
			dep[i]=0;
		}
		tot=0;
		for(int i=1;i<n;i++){
			int u,v;
			u=kd();v=kd();
			addedge(u,v);
			addedge(v,u);
		}
		cnt=0;
		dfs1(1);
		dfs2(1,1);
		build(1,1,n);
		k=0;
		while(m--){
			int opt=kd(),u=kd(),v=kd();
			if(opt==1){
				lca_1(u,v);
			}
			else{
				printf("%d\n",lca_2(u,v));
			}
		}
	}
	return 0;
}