CodeForces - 691D
有一说一,我荒了两个星期,然后感觉变菜了好多((
我又开始复健了
–>Link
D - Swaps in Permutation
- 题意:给你一串长为n的数列,m个数对(下标)两两连通,连通内可任意交换数,求可交换得到的最大字典序的数列。
- 思路:其实并查集是很容易想到的。在网上找了一些做法,我很中意这种写法:
1 开vector数组存储,并dfs
2 存储需要操作的下标(set),存储操作的映射(vector),对后者排序,前者不变,达到在特定的下标中进行操作的效果
#include<cassert>
#include<string>
#include<cmath>
#include<cstring>
#include<stack>
#include<iostream>
#include<map>
#include<set>
#include<algorithm>
#include<vector>
#include<cstdlib>
#pragma warning(disable:4996)
#define inf 0x3f3f3f3f
#define linf 0x3f3f3f3f3f3f3f
#define itn int
#define ll long long
#define mes(a,k) memset(a,k,sizeof(a))
//#define max(a,b) a>b?a:b
//#define min(a,b) a<b?a:b
#define eps 1e-8
//#define pb(a) push_back(a)
using namespace std;
const int N = 2e5 + 5;
using namespace std;
int a[100006];
set<int> se, index;//
bool vis[100006];
vector<int> arr[100006], temp;
void io() { ios::sync_with_stdio(false), cin.tie(0), cout.tie(0); }
void dfs(int x) {
vis[x] = 1;
temp.push_back(a[x]);
index.insert(x);
for (int y : arr[x]) {
if (!vis[y])
dfs(y);
}
}
int main() {
io();
int n, m, j = 0;
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
while (m--) {
int l, r;
cin >> l >> r;
arr[l].push_back(r);
arr[r].push_back(l);
se.insert(l);
se.insert(r);
}
//以前总是用迭代器来着
for (itn x : se) {
if (!vis[x]) {
index.clear();
temp.clear();
dfs(x);
//逆向排序
sort(temp.rbegin(), temp.rend());
j = 0;
for (int i : index) {///!!!
a[i] = temp[j++];
}
}
}
for (int i = 1; i <= n; i++) {
cout << a[i] << " ";
}
return 0;
}