「NOI2021」轻重边

watersail / 2024-10-22 / 原文

  • 时隔三年,自己战胜了三年前的自己,独立完成了这道NOI2021的Day1T1
  • 点边转化要减1
点击查看代码
#include <bits/stdc++.h>
using namespace std;
vector<int>a[100005];
int dfn[100005],d[100005],s[100005],z[100005],nxt[100005],h[100005],fa[100005],tot;
struct t1
{
	int l,r,va,sum,tag;
}t[400005];
void dfs1(int n1)
{
	s[n1]=1;
	for(int i=0;i<a[n1].size();i++)
	{
		if(a[n1][i]!=fa[n1])
		{
			d[a[n1][i]]=d[n1]+1;
			fa[a[n1][i]]=n1;
			dfs1(a[n1][i]);
			s[n1]+=s[a[n1][i]];
			if(s[a[n1][i]]>s[z[n1]])
			{
				z[n1]=a[n1][i];
			}
		}
	}
}
void dfs2(int n1)
{
	dfn[n1]=++tot;
	if(z[n1])
	{
		nxt[n1]=z[n1];
		h[z[n1]]=h[n1];
		dfs2(z[n1]);
	}
	for(int i=0;i<a[n1].size();i++)
	{
		if(!dfn[a[n1][i]])
		{
			h[a[n1][i]]=a[n1][i];
			dfs2(a[n1][i]);
		}
	}
}
void build(int p,int l,int r)
{
	t[p].l=l;
	t[p].r=r;
	t[p].va=-1;
	t[p].sum=0;
	t[p].tag=0;
	if(l==r)
	{
		return;
	}
	int mid=(l+r)>>1;
	build(p*2,l,mid);
	build(p*2+1,mid+1,r);
}
int len(int p)
{
	return t[p].r-t[p].l+1;
}
void pushdown(int p)
{
	if(t[p].va>=0)
	{
		int va=t[p].va;
		t[p].va=-1;
		t[p*2].va=va;
		t[p*2+1].va=va;
		t[p*2].sum=len(p*2)*va;
		t[p*2+1].sum=len(p*2+1)*va;
	}
}
void change1(int p,int l,int r,int va)
{
	if(l<=t[p].l&&r>=t[p].r)
	{
		t[p].va=va;
		t[p].sum=(va*(t[p].r-t[p].l+1));
		return;
	}
	pushdown(p);
	int mid=(t[p].l+t[p].r)>>1;
	if(l<=mid)
	{
		change1(p*2,l,r,va);
	}
	if(r>mid)
	{
		change1(p*2+1,l,r,va);
	}
	t[p].sum=t[p*2].sum+t[p*2+1].sum;
}
void change2(int p,int l,int r,int va)
{
	if(l<=t[p].l&&r>=t[p].r)
	{
		t[p].tag=va;
		return;
	}
	int mid=(t[p].l+t[p].r)>>1;
	if(l<=mid)
	{
		change2(p*2,l,r,va);
	}
	if(r>mid)
	{
		change2(p*2+1,l,r,va);
	}
}
int ask1(int p,int l,int r)
{
	if(l<=t[p].l&&r>=t[p].r)
	{
		return t[p].sum;
	}
	pushdown(p);
	int va=0;
	int mid=(t[p].l+t[p].r)>>1;
	if(l<=mid)
	{
		va+=ask1(p*2,l,r);
	}
	if(r>mid)
	{
		va+=ask1(p*2+1,l,r);
	}
	return va;
}
int ask2(int p,int x)
{
	if(t[p].l==t[p].r)
	{
		return t[p].tag;
	}
	int va=t[p].tag;
	int mid=(t[p].l+t[p].r)>>1;
	if(x<=mid)
	{
		va=max(va,ask2(p*2,x));
	}
	else
	{
		va=max(va,ask2(p*2+1,x));
	}
	return va;
}
void Change(int u,int v,int i)
{
	if(d[u]>d[v])
	{
		swap(u,v); 
	}
	if(u!=h[u])
	{
		change1(1,dfn[u]-1,dfn[u]-1,0);
	}
	if(nxt[v])
	{
		change1(1,dfn[v],dfn[v],0);
	}
	if(u!=v)
	{
		change1(1,dfn[u],dfn[v]-1,1);
	}
	change2(1,dfn[u],dfn[v],i);
}
int Ask(int u,int v)
{
	if(u!=v)
	{
		return ask1(1,min(dfn[u],dfn[v]),max(dfn[u],dfn[v])-1);
	}
	return 0;
}
int main()
{
    freopen("edge.in","r",stdin);
    freopen("edge.out","w",stdout);
	ios::sync_with_stdio(false);
	cin.tie(0);
	int T;
	cin>>T;
	while(T--)
	{
		int n,m;
		cin>>n>>m;
		tot=0;
		for(int i=1;i<=n;i++)
		{
			a[i].clear();
			dfn[i]=0;
			z[i]=0;
			nxt[i]=0;
		}
		build(1,1,n);
		for(int i=1;i<n;i++)
		{
			int u,v;
			cin>>u>>v;
			a[u].push_back(v);
			a[v].push_back(u);
		}
		d[1]=1;
		dfs1(1);
		h[1]=1;
		dfs2(1);
		for(int i=1;i<=m;i++)
		{
			int opt,u,v;
			cin>>opt>>u>>v;
			if(opt==1)
			{
				while(h[u]!=h[v])
				{
					if(d[h[u]]<d[h[v]])
					{
						swap(u,v);
					}
					Change(u,h[u],i);
					u=fa[h[u]];
				}
				Change(u,v,i);
			}
			else
			{
				int ans=0;
				while(h[u]!=h[v])
				{
					if(d[h[u]]<d[h[v]])
					{
						swap(u,v);
					}
					ans+=Ask(u,h[u]);
					if(ask2(1,dfn[h[u]])==ask2(1,dfn[fa[h[u]]]))
					{
						ans+=(ask2(1,dfn[h[u]])!=0);
					}
					u=fa[h[u]];
				}
				ans+=Ask(u,v);
				cout<<ans<<"\n";
			}
		}
	}
	return 0;
}