11.15 模拟 t3 rainbow


11.15 模拟 t3 rainbow

给出一个 \(n\) 个点 \(m\) 条边的图,每个点度数最多为 \(2\) . 第 \(i\) 个点颜色为 \(1\)\(a_i\) .

如果有多少种染色的方法,使得相连的两个点颜色不相同 . 模 \(998244353\) .

\(1\leq m\leq n\leq 2\cdot 10^5,1\leq a_i\leq 2\cdot 10^5\)

如果是链的情况,就是

考虑如何求出环的,如果断掉一条边,就形成了环,但是第一个点和最后一个点的颜色可能相同 .

考虑容斥 ,把环上 \(a_i\) 最小的那个点放在链的开头 . 考虑环的结束最后 \(k\) 个点一定和开头相同 .

方案数就是链的方案数 - 开头和最后 \(1\) 个点相同的方案数 + 开头和最后 \(2\) 个点相同的方案数 - \(\cdots\)

时间复杂度 : \(O(n)/O(n\log n)\)

空间复杂度 : \(O(n)\)

code
#include
using namespace std;
const int N=2e5+10;
const int mod=998244353;
int n,m,mxv;
int a[N];
bool vis[N];
vectorg[N];
vectorv;
int ans=1;
class node{public:int val,sz,tg1,tg2;}ts[N<<2];
void build(int x,int l,int r){
	if(l==r){
		ts[x]=(node){0,1,0,0};
		return;
	}
	int mid=(l+r)>>1;
	build(x<<1,l,mid);
	build(x<<1|1,mid+1,r);
	ts[x]=(node){0,ts[x<<1].sz+ts[x<<1|1].sz,0,0};
}
inline void pd(int x){
	if(!ts[x].tg1&&!ts[x].tg2)return;
	if(ts[x].tg1){
		ts[x<<1].val=ts[x<<1|1].val=0;
		ts[x<<1].tg1=ts[x<<1|1].tg1=1;
		ts[x<<1].tg2=ts[x<<1|1].tg2=0;
		ts[x].tg1=0;
	}
	if(ts[x].tg2){
		ts[x<<1].val=(ts[x<<1].val+1ll*ts[x<<1].sz*ts[x].tg2%mod)%mod;
		ts[x<<1|1].val=(ts[x<<1|1].val+1ll*ts[x<<1|1].sz*ts[x].tg2%mod)%mod;
		ts[x<<1].tg2=(ts[x<<1].tg2+ts[x].tg2)%mod;
		ts[x<<1|1].tg2=(ts[x<<1|1].tg2+ts[x].tg2)%mod;
		ts[x].tg2=0;
	}
}
void upd(int x,int l,int r,int cl,int cr,int val){
	if(l==cl&&r==cr){
		if(l!=r)pd(x);
		ts[x].val=(ts[x].val+1ll*ts[x].sz*val%mod)%mod;
		ts[x].tg2=(ts[x].tg2+val)%mod;
		return;
	}
	pd(x);
	int mid=(l+r)>>1;
	if(cr<=mid)upd(x<<1,l,mid,cl,cr,val);
	else if(mid+1<=cl)upd(x<<1|1,mid+1,r,cl,cr,val);
	else upd(x<<1,l,mid,cl,mid,val),upd(x<<1|1,mid+1,r,mid+1,cr,val);
	ts[x].val=(ts[x<<1].val+ts[x<<1|1].val)%mod;
}
void mdf(int x,int l,int r,int cl,int cr){
	if(l==cl&&r==cr){
		if(l!=r)pd(x);
		ts[x].val=0;
		ts[x].tg1=1;
		ts[x].tg2=0;
		return;
	}
	pd(x);
	int mid=(l+r)>>1;
	if(cr<=mid)mdf(x<<1,l,mid,cl,cr);
	else if(mid+1<=cl)mdf(x<<1|1,mid+1,r,cl,cr);
	else mdf(x<<1,l,mid,cl,mid),mdf(x<<1|1,mid+1,r,mid+1,cr);
	ts[x].val=(ts[x<<1].val+ts[x<<1|1].val)%mod;
}
int qry(int x,int l,int r,int pos){
	if(l==r)return ts[x].val;
	pd(x);
	int mid=(l+r)>>1;
	if(pos<=mid)return qry(x<<1,l,mid,pos);
	else return qry(x<<1|1,mid+1,r,pos);
}
void dfs(int x){
	vis[x]=true;
	v.push_back(x);
	for(int i=0;i<(int)g[x].size();i++){
		int to=g[x][i];
		if(!vis[to]){
			dfs(to);
		}
	}
}
void solv_line(){
	mdf(1,1,mxv,1,mxv);
	int tmp=1;
	for(int i=0;i<(int)v.size();i++){
		if(i==0)upd(1,1,mxv,1,a[v[i]],1);
		else{
			int val=ts[1].val;
			if(a[v[i]]>=a[v[i-1]]){
				if(a[v[i-1]]+1<=a[v[i]])
					upd(1,1,mxv,a[v[i-1]]+1,a[v[i]],(mod-val)%mod);
				upd(1,1,mxv,1,a[v[i-1]],(mod-val)%mod);
			}else{
				mdf(1,1,mxv,a[v[i]]+1,a[v[i-1]]);
				upd(1,1,mxv,1,a[v[i]],(mod-val)%mod);
			}
			tmp=-tmp;
		}
	}
	int res=(ts[1].val*tmp+mod)%mod;
	ans=1ll*ans*res%mod;	
}
void solv_cycle(){
	mdf(1,1,mxv,1,mxv);
	int mn=mxv+1,id=-1;
	for(int i=0;i<(int)v.size();i++)if(a[v[i]]vec;
	for(int i=id;i<(int)v.size();i++)vec.push_back(v[i]);
	for(int i=0;ires; 
	int tmp=1;
	for(int i=0;i<(int)v.size();i++){
		if(i==0)upd(1,1,mxv,1,a[v[i]],1);
		else{
			int val=ts[1].val;
			if(a[v[i-1]]<=a[v[i]]){
				if(a[v[i-1]]+1<=a[v[i]])
					upd(1,1,mxv,a[v[i-1]]+1,a[v[i]],(mod-val)%mod);
				upd(1,1,mxv,1,a[v[i-1]],(mod-val)%mod);
			}else{
				mdf(1,1,mxv,a[v[i]]+1,a[v[i-1]]);
				upd(1,1,mxv,1,a[v[i]],(mod-val)%mod);
			}
			tmp=-tmp;
			res.push_back((tmp*ts[1].val+mod)%mod);
		}	
	} 
	int result=0;
	for(int i=(int)res.size()-1;i>=0;i--){
		if(((int)res.size()-i)&1)result=(result+res[i])%mod;
		else result=(result-res[i]+mod)%mod;
	}
	ans=1ll*ans*result%mod;
}
int main(){
	freopen("rainbow.in","r",stdin);
	freopen("rainbow.out","w",stdout);
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	cin>>n>>m;
	for(int i=0;i>a[i];
	mxv=0;
	for(int i=0;i>u>>v;
		u--;v--;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	for(int i=0;i