找出每个联通块最大值最小值,两者之间的所有数必须在同一个联通块内,将所有的最大值最小值找出来,将他们抽象成区间,区间有重复的就合并成一个,
然后暴力找出这个区间中的不在这个联通块的数,并查集连一下。
水体。。
B题的模拟模了半天最后还挂了,下次就先往后做。
晚上写题真的懵逼啥也想不到,烦。。。。。
时间复杂度O(n + m)
#include <bits/stdc++.h>
using namespace std;
const int N = 200005;
struct node {
int x, y;
}T[N];
std::vector<int> v[N];
int vis[N];
int maxn,minx;
void dfs(int x){
for(int i = 0; i < v[x].size(); ++ i){
int y = v[x][i];
if(!vis[y]){
maxn = max(maxn, y), minx = min(minx, y);
vis[y] = 1;
dfs(y);
}
}
}
bool cmp(node a,node b){
return a.x == b.x? a.y > b.y: a.x < b.x;
}
int pre[N];
int finds(int x){
return x == pre[x]?x: pre[x] = finds(pre[x]);
}
void unions(int x,int y){
int xx = finds(x);
int yy = finds(y);
pre[xx] = yy;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i = 0 ;i <= n; ++i){
pre[i] = i;
}
for(int i = 0 ;i < m; ++i ){
int x, y;
scanf("%d%d",&x,&y);
v[x].push_back(y);
v[y].push_back(x);
unions(x, y);
}
int len = 0;
for(int i = 1; i <= n; ++i ){
if(!vis[i] && v[i].size()){
maxn = i, minx = i;
vis[i] = 1;
dfs(i);
T[len++] = {minx, maxn};
}
}
sort(T , T + len, cmp);
vector<pair<int ,int>> ans;
for(int i = 0 ; i < len ; i ++){
int l = T[i].x;
int j = i + 1;
int r = T[i].y;
while(j < len){
if(T[j].x > r) break;
r = max(r , T[j].y);
j ++;
}
i = j - 1;
for(int k = l + 1; k <= r; ++k ){
int x= finds(l), y = finds(k);
if(finds(l) != finds(k)){
ans.push_back(make_pair(l, k));
pre[x] = y;
}
}
}
cout << ans.size() <<endl;
}