• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 众包
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
未来が好き!
博客园    首页    新随笔    联系   管理    订阅  订阅
Educational Codeforces Round 14 D. Swaps in Permutation

题目链接

分析:一些边把各个节点连接成了一颗颗树。因为每棵树上的边可以走任意次,所以不难想出要字典序最大,就是每棵树中数字大的放在树中节点编号比较小的位置。

我用了极为暴力的方法,先dfs每棵树,再用了优先队列。我估计最大复杂度约在O(Nlog(N)),理论上应该跑不过。因为再cf上做题,看见5s时限,强行上了。很侥幸,在4秒的时候过了= =。

/*****************************************************/
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <map>
#include <set>
#include <ctime>
#include <stack>
#include <queue>
#include <cmath>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <sstream>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
#define   offcin        ios::sync_with_stdio(false)
#define   sigma_size    26
#define   lson          l,m,v<<1
#define   rson          m+1,r,v<<1|1
#define   slch          v<<1
#define   srch          v<<1|1
#define   sgetmid       int m = (l+r)>>1
#define   LL            long long
#define   ull           unsigned long long
#define   mem(x,v)      memset(x,v,sizeof(x))
#define   lowbit(x)     (x&-x)
#define   bits(a)       __builtin_popcount(a)
#define   mk            make_pair
#define   pb            push_back
#define   fi            first
#define   se            second

const int    INF    = 0x3f3f3f3f;
const LL     INFF   = 1e18;
const double pi     = acos(-1.0);
const double inf    = 1e18;
const double eps    = 1e-9;
const LL     mod    = 1e9+7;
const int    maxmat = 10;
const ull    BASE   = 31;

/*****************************************************/

const int maxn = 1e6 + 5;
std::vector<int> G[maxn];
int N, M;
int p[maxn];
bool vis[maxn];
struct Node {
    int val;
    bool operator <(const Node &rhs) const {
        return val > rhs.val;
    }
};
priority_queue<Node> q;
priority_queue<int> ans;
void dfs(int u, int fa) {
    if (vis[u]) return;
    vis[u] = true;
    ans.push(p[u]);
    q.push((Node){u});
    for (int i = 0; i < G[u].size(); i ++) {
        int v = G[u][i];
        if (v == fa) continue;
        dfs(v, u);
    }
}
int main(int argc, char const *argv[]) {
    cin>>N>>M;
    mem(vis, false);
    for (int i = 1; i <= N; i ++) scanf("%d", p + i);
    for (int i = 0; i < M; i ++) {
        int u, v;
        scanf("%d%d", &u, &v);
        G[u].pb(v);
        G[v].pb(u);
    }
    for (int i = 1; i <= N; i ++) {
        if (!vis[i]) dfs(i, -1);
        while (!ans.empty()) {
            int tmp = ans.top(); ans.pop();
            Node x = q.top(); q.pop();
            int id = x.val;
            p[id] = tmp;
        }
    }
    for (int i = 1; i <= N; i ++) cout<<p[i]<<" ";
    return 0;
}

正解没有那么暴力啊。正解是通过并查集来区分树。因为并查集的原因,遍历点的时候一定是从小到大的,省去了对位置的排序,复杂度又降了一个常数。这里只需要对各个树中的值排序就行了。复杂度比我的方法小了太多。用vector就可以了。

/*****************************************************/
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <map>
#include <set>
#include <ctime>
#include <stack>
#include <queue>
#include <cmath>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <sstream>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
#define   offcin        ios::sync_with_stdio(false)
#define   sigma_size    26
#define   lson          l,m,v<<1
#define   rson          m+1,r,v<<1|1
#define   slch          v<<1
#define   srch          v<<1|1
#define   sgetmid       int m = (l+r)>>1
#define   LL            long long
#define   ull           unsigned long long
#define   mem(x,v)      memset(x,v,sizeof(x))
#define   lowbit(x)     (x&-x)
#define   bits(a)       __builtin_popcount(a)
#define   mk            make_pair
#define   pb            push_back
#define   fi            first
#define   se            second

const int    INF    = 0x3f3f3f3f;
const LL     INFF   = 1e18;
const double pi     = acos(-1.0);
const double inf    = 1e18;
const double eps    = 1e-9;
const LL     mod    = 1e9+7;
const int    maxmat = 10;
const ull    BASE   = 31;

/*****************************************************/

const int maxn = 1e6 + 5;
int par[maxn], p[maxn];
std::vector<int> pos[maxn];
std::vector<int> num[maxn];
int N, M;
void init() {
    for (int i = 1; i <= N; i ++) par[i] = i;
}
int findpar(int x) {
    return par[x] = (par[x] == x ? x : findpar(par[x]));
}
void unite(int x, int y) {
    x = findpar(x), y = findpar(y);
    if (x == y) return;
    par[x] = y;
}
int main(int argc, char const *argv[]) {
    cin>>N>>M;
    init();
    for (int i = 1; i <= N; i ++) scanf("%d", p + i);
    for (int i = 0; i < M; i ++) {
        int u, v;
        scanf("%d%d", &u, &v);
        unite(u, v);
    }
    for (int i = 1; i <= N; i ++) {
        int x = findpar(i);
        pos[x].pb(i);
        num[x].pb(-p[i]);
    }
    for (int i = 1; i <= N; i ++) {
        sort(num[i].begin(), num[i].end());
        for (int j = 0; j < pos[i].size(); j ++) {
            int id = pos[i][j];
            p[id] = -num[i][j];
        }
    }
    for (int i = 1; i <= N; i ++) cout<<p[i]<<" ";
    return 0;
}
posted on 2016-09-08 19:41  未来が好き!  阅读(132)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3