其他分享
首页 > 其他分享> > ! JOISC2020DAY2变色龙之恋

! JOISC2020DAY2变色龙之恋

作者:互联网



一只变色龙与另外的变色龙颜色相同只可能有三种情况——喜欢,被喜欢和原颜色一样

我们将这样的变色龙对连上边,那么因为性别不同的限定,一定是一个二分图

这样可以二分,若加入\(u\)后颜色数不变那么这里面一定存在可以连边的变色龙对

我们可以黑白染色然后分开二分,这样原集合大小即为颜色数

得到之后,每个点再做两次即可找到喜欢的对象,排除后就剩下颜色相同的了

#include "chameleon.h"
#include<bits/stdc++.h>
using namespace std;
namespace mine{
const int N=1e5+4;
#define vi vector<int>
vi e[N],ask;
int n,col[N],v[2][N],vc[2],pre[N];
bool b[N],use[N];
void dfs(int x,int c){
	col[x]=c;
	for(auto v:e[x])
		if(col[v]==-1)dfs(v,c^1);
}
inline void getcol(int i){
	memset(col+1,-1,n<<2);
	for(int j=1;j<i;j++)
		if(col[j]==-1)dfs(j,0);
	memset(vc,0,8);
	for(int j=1;j<i;j++)v[col[j]][++vc[col[j]]]=j;
} 
inline bool ck(int p,int l,int r,int i){
	ask.clear();ask.push_back(i);
	for(int j=l;j<=r;j++)
		if(!b[v[p][j]])ask.push_back(v[p][j]);
	return Query(ask)<ask.size();
}
int query(int p,int l,int r,int i){
	if(l==r)return v[p][l];
	int mid=l+r>>1;
	return ck(p,l,mid,i)?query(p,l,mid,i):query(p,mid+1,r,i); 
}
inline void solve(int nn){
	n=nn<<1;
	for(int i=1,x;i<=n;i++){
		getcol(i);
		memset(b+1,0,n);
		for(int o=0;o<2;o++)
			for(;ck(o,1,vc[o],i);){
				x=query(o,1,vc[o],i);
				e[i].push_back(x);
				e[x].push_back(i);
				b[x]=1;
			}
	}
	ask.resize(3);
	for(int i=1,x;i<=n;i++){
		if(e[i].size()==1){
			if(use[i])continue;
			Answer(i,e[i][0]);
			use[i]=use[e[i][0]]=1;
			continue;
		}
		ask[0]=i;
		ask[1]=e[i][0];ask[2]=e[i][1];x=Query(ask);
		if(x==1){
			swap(e[i][2],e[i][0]);
			pre[e[i][0]]=i;
			continue;
		}
		ask[2]=e[i][2];x=Query(ask);
		if(x==1){
			swap(e[i][1],e[i][0]);
			pre[e[i][0]]=i;
			continue;
		}
		pre[e[i][0]]=i;
	}
	for(int i=1,x;i<=n;i++){
		if(use[i])continue;
		if(pre[i]==e[i][1])x=e[i][2];
		else x=e[i][1];
		Answer(i,x);
		use[i]=use[x]=1;
	}
}
}
void Solve(int N){
	mine::solve(N);
}

标签:颜色,之恋,JOISC2020DAY2,void,mid,int,变色龙,col
来源: https://www.cnblogs.com/aurora2004/p/12555434.html