Educational Codeforces Round 14 D 并查集



链接:戳这里


D. Swaps in Permutation
time limit per test5 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
You are given a permutation of the numbers 1, 2, ..., n and m pairs of positions (aj, bj).

At each step you can choose a pair from the given positions and swap the numbers in that positions. What is the lexicographically maximal permutation one can get?

Let p and q be two permutations of the numbers 1, 2, ..., n. p is lexicographically smaller than the q if a number 1 ≤ i ≤ n exists, so pk = qk for 1 ≤ k < i and pi < qi.

Input
The first line contains two integers n and m (1 ≤ n, m ≤ 106) — the length of the permutation p and the number of pairs of positions.

The second line contains n distinct integers pi (1 ≤ pi ≤ n) — the elements of the permutation p.

Each of the last m lines contains two integers (aj, bj) (1 ≤ aj, bj ≤ n) — the pairs of positions to swap. Note that you are given a positions, not the values to swap.

Output
Print the only line with n distinct integers p'i (1 ≤ p'i ≤ n) — the lexicographically maximal permutation one can get.

Example
input
9 6
1 2 3 4 5 6 7 8 9
1 4
4 7
2 5
5 8
3 6
6 9
output
7 8 9 4 5 6 1 2 3


题意:

长度为n个正整数序列(1<=ai<=n)且严格两两互不相等,给出m个选择的操作swap(x,y),满足交换a[x],a[y]

通过选择任意次m个操作使得字典序最大


思路:

对于swap(a,b) swap(b,c) swap(c,d)这样的交换操作,可以理解为(a,b,c,d)四个数排序之后从大到小依次放

并查集把每一块里面的数都分出来,然后各自块都从大到小依次放

其实主要是模拟,复杂度的话怎么都不会超时


代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<vector>
#include <ctime>
#include<queue>
#include<set>
#include<map>
#include<list>
#include<stack>
#include<iomanip>
#include<cmath>
#include<bitset>
#define mst(ss,b) memset((ss),(b),sizeof(ss))
///#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef long double ld;
#define INF (1ll<<60)-1
#define Max 1e9
using namespace std;
int n,m;
struct node{
    int a,id;
}s[1000100];
int fa[1000100];
int Find(int x){
    if(x!=fa[x])
        fa[x]=Find(fa[x]);
    return fa[x];
}
struct B{
    int v,id;
    B(int v=0,int id=0):v(v),id(id){}
    bool operator < (const B &a)const{
        return v<a.v;
    }
};
vector<B> V[1000100];
int anw[1000100];
int tmp[1000100];
int Id[1000100];
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) {
        scanf("%d",&s[i].a);
        s[i].id=i;
    }
    for(int i=1;i<=n;i++) fa[i]=i;
    for(int i=1;i<=m;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        int X=Find(x);
        int Y=Find(y);
        if(X!=Y){
            fa[X]=Y;
        }
    }
    int cnt=0;
    for(int i=1;i<=n;i++){
        int x=Find(i);
        if(i==x) tmp[++cnt]=x;
        V[x].push_back(B(s[i].a,s[i].id));
    }
    for(int i=1;i<=cnt;i++){
        int x=tmp[i];
        sort(V[x].begin(),V[x].end());
        int m=V[x].size()-1;
        int num=0;
        for(int j=m;j>=0;j--){
            Id[++num]=V[x][j].id;
        }
        sort(Id+1,Id+num+1);
        for(int j=m;j>=0;j--){
            B t=V[x][j];
            int v=t.v;
            int id=Id[m-j+1];
            anw[id]=v;
        }
    }
    for(int i=1;i<=n;i++) printf("%d ",anw[i]);printf("\n");
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值