ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[NOI2021]轻重边

2022-07-03 23:33:09  阅读:141  来源: 互联网

标签:int fy top mid NOI2021 fx dfn 轻重


这个题有两个方法,都得掌握。(LCT就算了)

一个方法不具有强的普遍性,但很巧妙,可以积累一下。边由两个端点组成。初始时各点的颜色互不相同,每次修改对路径上的点赋予独一无二的颜色,可以使得黑边等价于两端点颜色相同,白边等价于颜色不同。这个做法能够成立主要是因为修改的方式比较特殊。具体的维护就是维护区间内的三个值:左端点颜色、右端点颜色、多少条边是黑边。树链剖分时再把接头处拼一下就行了,代码难度较低。

另一个方法具有较强的普遍性,可以对于“一次性将路径上的边都变成黑边、邻边都变成白边”这么特殊的修改方式之外的还奏效,它适用于针对“修改一个路径、邻边受到影响”类的很多问题。用线段树记录区间内的两个值:自己的父边的状态、自己的轻边有几条是黑色。通常都可以做了。这道题也可以,而且蛮简单的,只需要注意最开始的点的重儿子的父边也要改哦。

下面的代码是方法一

#include <bits/stdc++.h>
using namespace std;
inline int read(){
	register char ch=getchar();register int x=0;
	while(ch<'0'||ch>'9')ch=getchar();
	while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	return x;
}
void print(int x){
	if(x/10)print(x/10);
	putchar(x%10+48);
}
const int N=1e5+5;
int n,q,noi,dfc,son[N],siz[N],top[N],fa[N],dep[N],dfn[N];
vector<int>G[N];
struct node {
	int lc,rc,s,tag;
}t[N<<2];
void dfs1(int x,int p){
	fa[x]=p,dep[x]=dep[p]+1,siz[x]=1;
	for(int y:G[x])if(y^p){
		dfs1(y,x);
		siz[x]+=siz[y];
		if(siz[y]>siz[son[x]])son[x]=y;
	}
}
void dfs2(int x,int p,int tp){
	dfn[x]=++dfc;
	top[x]=tp;
	if(son[x])dfs2(son[x],x,tp);
	for(int y:G[x])if(y^p){
		if(y==son[x])continue;
		dfs2(y,x,y);
	}
}
void pushdown(int l,int r,int k){
	if(!t[k].tag)return;
	int mid=l+r>>1;
	t[k<<1].tag=t[k<<1|1].tag=t[k].tag;
	t[k<<1].lc=t[k<<1].rc=t[k<<1|1].lc=t[k<<1|1].rc=t[k].tag;
	t[k<<1].s=mid-l,t[k<<1|1].s=r-mid-1;
	t[k].tag=0;
}
void pushup(int k){
	t[k].s=(t[k<<1].rc==t[k<<1|1].lc)+t[k<<1].s+t[k<<1|1].s;
	t[k].lc=t[k<<1].lc,t[k].rc=t[k<<1|1].rc;
}
void build(int l,int r,int k){
	t[k].tag=0;
	if(l==r){t[k].s=0;t[k].lc=t[k].rc=l;return;}
	int mid=l+r>>1;
	build(l,mid,k<<1),build(mid+1,r,k<<1|1);
	pushup(k);
}
void chg(int L,int R,int v,int l,int r,int k){
	if(L<=l&&r<=R){t[k].s=r-l;t[k].lc=t[k].rc=v;t[k].tag=v;return;}
	pushdown(l,r,k);
	int mid=l+r>>1;
	if(L<=mid)chg(L,R,v,l,mid,k<<1);
	if(R>mid)chg(L,R,v,mid+1,r,k<<1|1);
	pushup(k);
}
int asks(int L,int R,int l,int r,int k){
	if(L<=l&&r<=R)return t[k].s;
	pushdown(l,r,k);
	int mid=l+r>>1,s=0;
	if(L<=mid)s+=asks(L,R,l,mid,k<<1);
	if(R>mid)s+=asks(L,R,mid+1,r,k<<1|1);
	if(L<=mid&&R>mid)s+=t[k<<1].rc==t[k<<1|1].lc;
	return s;
}
int asklc(int L,int R,int l,int r,int k){
	if(L==l)return t[k].lc;
	pushdown(l,r,k);
	int mid=l+r>>1;
	if(L<=mid)return asklc(L,R,l,mid,k<<1);
	return asklc(L,R,mid+1,r,k<<1|1);
}
int askrc(int L,int R,int l,int r,int k){
	if(R==r)return t[k].rc;
	pushdown(l,r,k);
	int mid=l+r>>1;
	if(R>mid)return askrc(L,R,mid+1,r,k<<1|1);
	return askrc(L,R,l,mid,k<<1);
}
void tchg(int x,int y){
	int fx=top[x],fy=top[y];
	while(fx!=fy){
		if(dep[fx]>dep[fy]){
			chg(dfn[fx],dfn[x],noi,1,n,1);
			x=fa[fx],fx=top[x];
		}
		else {
			chg(dfn[fy],dfn[y],noi,1,n,1);
			y=fa[fy],fy=top[y];
		}
	}
	if(dfn[x]>dfn[y])swap(x,y);
	chg(dfn[x],dfn[y],noi,1,n,1);
}
int task(int x,int y){
	int fx=top[x],fy=top[y],s=0,xc=0,yc=0;
	while(fx!=fy){
		if(dep[fx]>dep[fy]){
			s+=asks(dfn[fx],dfn[x],1,n,1);
			s+=xc==askrc(dfn[fx],dfn[x],1,n,1),xc=asklc(dfn[fx],dfn[x],1,n,1);
			x=fa[fx],fx=top[x];
		}
		else {
			s+=asks(dfn[fy],dfn[y],1,n,1);
			s+=yc==askrc(dfn[fy],dfn[y],1,n,1),yc=asklc(dfn[fy],dfn[y],1,n,1);
			y=fa[fy],fy=top[y];
		}
	}
	if(dfn[x]<dfn[y]){
		s+=asks(dfn[x],dfn[y],1,n,1);
		s+=yc==askrc(dfn[x],dfn[y],1,n,1);
		s+=xc==asklc(dfn[x],dfn[y],1,n,1);
	}
	else {
		s+=asks(dfn[y],dfn[x],1,n,1);
		s+=yc==asklc(dfn[y],dfn[x],1,n,1);
		s+=xc==askrc(dfn[y],dfn[x],1,n,1);
	}
	return s;
}
void solve(){
	n=noi=read(),q=read();
	dfc=0;for(int i=1;i<=n;i++)G[i].clear(),son[i]=top[i]=siz[i]=dfn[i]=dep[i]=0;
	for(int i=1,u,v;i<n;i++){
		u=read(),v=read();
		G[u].push_back(v),G[v].push_back(u);
	}
	build(1,n,1);
	dfs1(1,0),dfs2(1,0,1);
	for(int i=1,op,u,v;i<=q;i++){
		op=read(),u=read(),v=read();//cout<<i<<'.';
		if(op==1)noi++,tchg(u,v);
		else print(task(u,v)),puts("");
	}
}
int main(){
	int T=read();
	while(T--)solve();
}

标签:int,fy,top,mid,NOI2021,fx,dfn,轻重
来源: https://www.cnblogs.com/impyl/p/16421421.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有