分析
交换对将序列分为(1,4,7)(2,5,8)(3,6,9)。所有数字只能在自己的“队伍”中移动,为了获得最大字典序,贪心将最大的数字放在前面输出即可。
问题即为:如何将数字分组,并输出最大数字?
解决
数据结构:大根堆,方便最后输出和弹出最大元素。
分组:利用并查集创建以每个father为代表的队伍,并将队伍放进大根堆。(大根堆以father为标识)。
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+7;
int n ,m , num[N],fa[N];
priority_queue<int> q[N];
int find(int x){
return x==fa[x] ? x:(fa[x]=find(fa[x]));//fa是自己说明没有fa,返回
}
void merge(int i ,int j){ //合并,即统一fa
int x=find(i),y=find(j);
if(x!=y)
fa[x]=y;
}
int main( )
{
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>num[i];
fa[i]=i;//fa都是自己
}
for(int i=1;i<=m;i++){
int x,y;
cin>>x>>y;
merge(x,y);//合并fa
}
for(int i=1;i<=n;i++)
q[find(i)].push(num[i]); //找到fa,每个fa为标识,创建大根堆
for(int i =1;i<=n;i++){
int a=find(i);//当前位置统一的fa
cout<<q[a].top()<<" ";//fa大根堆中最大的
q[a].pop();
}
//1 4 7 |2 5 8
//fa分别是1和2,代表两个大根堆
//如果遇到某一个位置找到fa是1,说明是1 4 7,那就把最大的输出(即尽可能把大的往前放
return 0;
}