首页 > 其他分享 >题解 ARC165F【Make Adjacent】

题解 ARC165F【Make Adjacent】

时间:2023-09-23 14:55:11浏览次数:40  
标签:int 题解 Make Adjacent 区间 逆序 include id 关键点

区间排序问题,主席树优化建图,最小字典序拓扑排序(priority_queue)

problem

给定一个长度为 \(n*2\) 的序列,其中每种元素恰好出现了 2 次。

允许每次选择任意两个相邻的元素交换。
那么必定存在一个最小 \(k\):使得 \(k\) 次交换以后所有相同的元素都是相邻的。

问恰好操作 \(k\) 次后,所有满足(相同的元素全都相邻)的方案中,最小字典序的一个方案。

solution

考虑这个是所谓的区间排序问题,所以我们考虑三种情况:区间有交不包含,区间包含,区间不交。

只要我们考虑了所有的区间对,所有的区间对都不交,那么就达到了最终状态,不妨考虑一个区间对:

有交不包含

形如 ([)] 的东西,考虑说,如果在最终排列中 ()[] 前面,然后考察它们的逆序对,这样的话有一个逆序对。如果在最终排列中 []() 前面,这样有三个逆序对,这样的最终排列一定不优,所以我们得出结论 ()[] 前面。

包含

形如 ([]) 的东西,你发现无论考虑 ()[] 的关系如何,逆序对个数都是 \(2\),于是他们的顺序无所谓。

无交

形如 ()[] 的东西,明显 ()[] 的前面是必须的,顺序不能调换。

所以有了这些结论我们就可以建出拓扑图进行最小字典序拓扑排序了。然后 \(n=2\times 10^5\) 的话,用主席树优化建图或者直接分治(分治相对好写一点)就行。拓扑排序将点分成关键点和非关键点,每次优先选非关键点,选关键点的时候选最小的。这样复杂度就对了(非关键点不要 priority_queue)

\(O(n\log n)\)

code

点击查看代码

#include <numeric>
#include <queue>
#include <cstdio>
#include <vector>
#include <cstring>
#include <cassert>
#include <algorithm>
using namespace std;
#ifdef LOCAL
#define debug(...) fprintf(stderr, ##__VA_ARGS__)
#else
#define debug(...) void(0)
#endif
typedef long long LL;
int n, L[200010], R[200010], id[200010];
int tot = 0;
vector<int> g[200010 << 6];
int deg[200010 << 6];
void add(int u, int v) {
    if (v) g[v].push_back(u), deg[u] += 1;
}
void solve(int l, int r) {
    if (l == r) return ;
    int mid = (l + r) >> 1;
    solve(l, mid), solve(mid + 1, r);
    for (int i = l; i <= mid; i++) id[i] = -id[i];
    sort(id + l, id + r + 1, [&](int i, int j) { return R[abs(i)] < R[abs(j)];});
    int pre = 0;
    for (int i = l; i <= r; i++) {
        if (id[i] > 0) add(id[i], pre);
        else {
            int p = ++tot;
            add(p, pre), add(p, -id[i]), pre = p;
            id[i] = -id[i];
        }
    }
}
void work() {
    queue<int> q;
    priority_queue<int, vector<int>, greater<int>> Q;
    auto push = [&](int u) {
        if (u <= n) Q.push(u);
        else q.push(u);
    };
    auto front = [&]() {
        int res;
        if (!q.empty()) res = q.front(), q.pop();
        else res = Q.top(), Q.pop();
        return res;
    };
    for (int i = 1; i <= tot; i++) if (!deg[i]) push(i);
    while (!q.empty() || !Q.empty()) {
        int u = front();
        if (u <= n) printf("%d %d ", u, u);
        for (int v: g[u]) if (--deg[v] == 0) push(v);
    }
    puts("");
}
int main() {
    scanf("%d", &n);
    for (int i = 1, x; i <= n << 1; i++) {
        scanf("%d", &x);
        if (!L[x]) L[x] = i; else R[x] = i;
    }
    tot += n;
    iota(id + 1, id + n + 1, 1);
    sort(id + 1, id + n + 1, [&](int i, int j) { return L[i] < L[j]; });
    solve(1, n);
    work();
    return 0;
}


标签:int,题解,Make,Adjacent,区间,逆序,include,id,关键点
From: https://www.cnblogs.com/caijianhong/p/solution-ARC165F.html

相关文章

  • 【POJ 1521】Entropy 题解(贪心算法+优先队列+哈夫曼树)
    熵编码器是一种数据编码方法,通过对删除了“浪费”或“额外”信息的消息进行编码来实现无损数据压缩。换句话说,熵编码去除了最初不需要的信息,以准确编码消息。高度的熵意味着一条消息包含大量浪费的信息;以ASCII编码的英文文本是具有极高熵的消息类型的示例。已经压缩的消息,如JPEG图......
  • 题解 CF1873H Mad City
    题意描述马塞尔和瓦勒里乌(Valeriu)所在的疯狂城市由\(n\)栋建筑和\(n\)条双向道路组成。马塞尔和瓦勒里乌(Valeriu)分别从\(a\)号和\(b\)号建筑开始。马塞尔想赶上瓦勒里乌(换句话说,与他在同一栋楼里或在同一条路上相遇)。在每次移动过程中,他们都会选择前往当前建筑的邻近建......
  • 'main' attribute cannot be used in a module that contains top-level code 问题解
    核心是@main注解在main.swift文件中,可以重新命名下参考资料https://stackoverflow.com/questions/73431031/swift-cli-app-main-attribute-cannot-be-used-in-a-module-that-contains-top-leve......
  • CF1842F Tenzing and Tree 题解
    TenzingandTree感觉很典型的题,就是树的重心+绝对值等式解法:以每个点\(i\)为根分别\(bfs\),得到一个距离数组\(dis\),取前\(k\)个值的权值为和,更新\(w[k]\)的值,\(n\)个点分别为根,更新\(n\)遍之后,得到\(w\)数组,则\((n-1)\timesi-w[i]\),即为\(i\)个点时候的......
  • 砝码称重 题解
    砝码称重题解前言这道题时限完全可以开到1s,空间也开不到1024kb白想那么多优化(不过这个复杂度可能是目前来看最合理(算出来保证能过)的。题意简述有一个长度为\(n\)的序列\(a\),有两种操作:把\(l\)到\(r\)的所有数改为\(x\);查询用\(l\)到\(r\)的所有数(每个数可......
  • 题解 AtCoder Beginner Contest 267 A~H
    ABC267solutionhttps://atcoder.jp/contests/abc267/ProblemA.Saturday题目描述输入一个表示星期的英文字符串,输出:还有多少天到星期六?solution依题意模拟。\(O(1)\)。ProblemB.Split?题目描述Robin有十个小球,如图排列成这样,然后Robin将一些球击飞了,他告诉你哪些......
  • Django跨域问题解决
    Django跨域问题解决今天在学习前端Vue框架的过程中,遇到了跨域相关问题问题1详情:AccesstoXMLHttpRequestat'http://127.0.0.1:8000/book/'fromorigin'http://localhost:63342'hasbeenblockedbyCORSpolicy:No'Access-Control-Allow-Origin'headerispre......
  • P5836 [USACO19DEC] Milk Visits S - 洛谷题解
     题目链接:[P5836] USACO19DEC] MilkVisitsS-洛谷|计算机科学教育新生态(luogu.com.cn)这道题可以用并查集来解决。题目中每个结点只有两个状态:H和G。那么我们可以推断出,只有当起点和终点间每个结点的状态相同但是起点(或者终点或起点到终点之间的某一点)与所需状态不同......
  • cmake添加 版本到代码中
    CMakeLists.txt:add_definitions(-DSYSMONITER_VER="${VER}")c++代码:voiddisplayVersion(){#ifdefSYSMONITER_VERstd::cout<<SYSMONITER_VER<<std::endl;#endif}编译命令:cmake..-DVER=$(date"+%Y%m%d%H%M%S")这里的date用......
  • cmake命令
    CMake是一个跨平台的开源构建工具,用于管理C++项目的构建过程。注意CMake命令语法不区分大小写cmake_minimum_required:指定项目所需的CMake的最低版本。cmake_minimum_required(VERSION<version>)project:定义项目的名称、版本和描述信息。project(<project_name>VERSIO......