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;
}

浙公网安备 33010602011771号