CWOI/ZROI 阿瓦的手套加强版

题目点这里

思路:

首先想到的思路是找到关联的数对 \((x_1,y_1)\)\((x_2,y_2)\) 满足其中任意两个数相等。从中可以知道这几双手套都是同一颜色。

但是数据量大,直接暴搜肯定不行。因此选择进行排序使数据先有序,而且是复杂度为
\(O(n)=n·logn\) 的排序,这里选择快排 \(x\) 为第一关键字, \(y\) 为第二关键字。

然后又有一个问题:每个与 \(y_i\) 相等的 x 都很容易找到,但是每个与 \(x_i\) 相等的 \(y\) 却仍然不好找,怎么办呢?

方法很简单:在输入 \((x_i,y_i)\) 的时候把 \((y_i,x_i)\) 加入数组,这样就通过第二个数对找到对应的第一个数对:

\[yi->(y_i,x_i)->(x_i,y_i)->xi \]

这时候就好想了,用深搜找到每个x对应的y对应的(一直递归)……就行了,并标记上颜色。

代码:

#include<bits/stdc++.h>
using namespace std;
long long n,m,t,ans=1,cl,ton[100005];
struct gloves{
	int x,y,c;
}g[200005];
bool cmpp(gloves a,gloves b){
	if(a.x>b.x)return 0;
	else if(a.x==b.x)return a.y<b.y;
	return 1;
}int bfind(int low,int high,int ta){
    while(low<=high){
        int mid=low+(high-low)/2;
        if(g[mid].x>ta)high=mid-1;
        else if(g[mid].x<ta)low=mid+1;
        else return mid;
    }
    return 0;
}void mfind(int i){
	g[i].c=cl;
	int j=0;
	while(g[i].x==g[i-1].x)i--;
	while(g[i].x==g[i+1].x){
		g[i].c=cl;
		j=bfind(j+1,2*t,g[i].y);
		if(j==0)continue;
		if(j<=t*2&&g[j].c==0)mfind(j);
		i++;
	}g[i].c=cl;
	j=bfind(j+1,2*t,g[i].y);
	if(j>0&&g[j].c==0)mfind(j);
}
int main(){
	cin>>n>>m>>t;
	for(int i=1;i<=t;i++){
		cin>>g[i].x>>g[i].y;
		ton[g[i].x]=1,ton[g[i].y]=1;
		g[i+t].y=g[i].x,g[i+t].x=g[i].y;
	}sort(g+1,g+1+2*t,cmpp);
	for(int i=1;i<=2*t;i++){
		if(g[i].c==0){
			cl++;
			mfind(i);
		}
	}for(int i=1;i<=n;i++)if(ton[i]==0)cl++;
	for(int i=1;i<=cl;i++)ans=(ans*m)%998244353;
	cout<<ans;
	return 0;
}
posted @ 2022-11-12 10:41  robinyqc  阅读(61)  评论(0)    收藏  举报