首页 > 其他分享 >题解 AtCoder wtf22_day1_b【Non-Overlapping Swaps】

题解 AtCoder wtf22_day1_b【Non-Overlapping Swaps】

时间:2023-10-12 18:55:06浏览次数:48  
标签:AtCoder Non ch int 题解 置换 交换 后继 include

题解 AtCoder wtf22_day1_b【Non-Overlapping Swaps】

problem

给定一个排列,要求交换最多 \(n-1\) 对元素,使得这个排列变成 [1,2,...,n] 的有序排列。

当然没有那么简单,对于交换还是有限制的,对于相邻的两次交换,不妨叫做 \((l_i, r_i)\) 和 \((l_{i+1}, r_{i+1})\),必须满足这两个交换所对应的区间,没有交集,即:

  • 要么 \(r_i <= l_{i+1}\);
  • 要么 \(r_{i+1} <= l_i\)。

请给出一种构造。

\(n\leq 200000\)。

solution

考虑对于一个置换环,如果能解决一个置换环的问题,那么在两个置换环中间插入 1 1 就能将两个置换环连接起来。所以我们只需要考虑一个置换环。

考虑一个置换环,我们连边 \(i\to p_i\),然后取出标号最小的两个元素,不妨记为 \(a,b\)。考虑构造:

  • 首先找到 \(a\) 的前驱,记为 \(c\),使 \(c\) 重新连向 \(b\),对 \(c\to b\) 所在的置换环(绿色)进行递归构造。
  • 然后交换 \(a,b\)。(浅蓝色)
  • 找到之前 \(a\) 的后继,记为 \(d\),将 \(a\)(现在在原来 \(b\) 的位置)重新连向 \(d\),对 \(a\to d\) 所在的置换环(棕色)进行递归构造。

正确性:

  • 不是 \(a,b,c,d\) 的点,都被交换到它的后继。
  • \(a\) 确实最后到达了 \(d\) 的位置,\(b\) 到达了 \(b\) 的后继,\(d\) 到达了 \(d\) 的后继,\(c\) 到达了 \(b\) 原来所有的位置后被 swap 到原来 \(a\) 的位置。
  • (这个题的位置关系很乱,本文统一使用“前驱” “后继”)
  • 做完绿色置换环后,交换 \(a, b\),不会产生冲突,因为根据定义,\(a,b\) 是标号最小的。如果冲突了说明其中有一个点的标号 \(<b\)。
  • 同理,交换 \(a, b\) 后做棕色置换环,不会产生冲突。

那么这是一个合法的构造,我们如果要实现这个过程有两种方法:

method 1

用一个 std::set 表示这个置换环,则我们可以轻易找出这个置换环的标号最小的两个节点。然后我们发现不能轻易地分裂两个置换环,因为时间复杂度会爆炸。考虑启发式分裂,每次将小的分裂出去;找到小的置换环,只需要使用两个指针在两个置换环上分别跳,谁先回到原点谁就是小置换环;这样判断的复杂度是 \(O(2siz_{small})\) 因此非常正确,然后在 set 中删数也是非常正确,一共 \(O(n\log^2n)\)。

method 2

考虑所谓拿出最小值的过程可以类比笛卡尔树,于是我们的惊人结论是将置换环拍成一行后,将最小的放在前面,然后建笛卡尔树。使用笛卡尔树构造方案,先递归左子树,然后交换它与父亲,然后递归右子树。这样就完美实现题目过程(最小的点相当于父亲,而次小相当于儿子,类似这样)。\(O(n)\)。至于为什么最小的要放在前面,因为最小的点作为树根,没有父亲提供中转。

code

//505161648
#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, a[1 << 18], vis[1 << 18], tim, ch[1 << 18][2];
int build(vector<int> h) {
    static int stk[1 << 18];
    int top = 0; ch[0][1] = stk[++top] = h[0];
    for (int p: h) {
        ch[p][0] = ch[p][1] = 0;
        if (p == h[0]) continue;
        while (top && stk[top] >= p) --top;
        ch[p][0] = ch[stk[top]][1];
        ch[stk[top]][1] = p;
        stk[++top] = p;
    }
    return ch[0][1];
}
void dfs(int p, int f) {
    if (!p) return ;
    dfs(ch[p][0], p);
    if (f) {
        int l = p, r = f;
        if (l > r) swap(l, r);
        printf("%d %d\n", l, r);
    }
    dfs(ch[p][1], p);
}
int mian() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
    printf("%d\n", n - 1);
    int last = 0;
    for (int i = 1; i <= n; i++) if (vis[i] < tim) {
        vector<int> h;
        for (int p = i; vis[p] < tim; p = a[p]) h.push_back(p), vis[p] = tim;
        reverse(h.begin(), h.end());
        rotate(h.begin(), prev(h.end()) ,h.end());
        if (last) printf("1 1\n");
        else last = i;
        dfs(build(h), 0);
    }
    return 0;
}
int main() {
    int T;
    scanf("%d", &T);
    while (T--) ++tim, mian();
    return 0;
}

标签:AtCoder,Non,ch,int,题解,置换,交换,后继,include
From: https://www.cnblogs.com/caijianhong/p/17753006.html

相关文章

  • 题解 CF486D Valid Sets
    题目链接相当牛逼。这种找数量的题型,确定树形\(dp\)没跑了。首先思考常规树形\(dp\),不难想到设\(f_{u,a,b}\)表示以\(u\)为根节点的子树内(包括点\(u\)),最大值是\(a\),最小值是\(b\)的连通子图数量,转移很容易,但是这样时间空间复杂度是\(\rmO(n^3)\),而且无论是状态上......
  • Debian12安装elasticsearch实践及问题解决方案
    一、安装安装其实很简单,直接上官网链接:下载地址,官网提供了所有安装方式,总一款适合你。我的目标系统是Debian12,包管理是apt-get,所以就以这个为示例,仅供参考。1、先选择需要安装的版本2、导入ElasticsearchPGP密钥wget-qO-https://artifacts.elastic.co/GPG-KEY-elastic......
  • 原创题题解
    实时更新。众所周知的,原创题就是即原神又创人的题。当然有的题不会放,等考了在放。波特问题描述流水线上有\(n\)个波特,每个波特有一个工作效能\(a_i\)。对于每一个波特,当它遇到一个工件时,它会对其进行加工,耗费\(1\)个单位时间,然后把它传递给它前面中工作效能最大的波特,......
  • #9134. 翻转硬币 题解
    首先考虑一些简单的情况,比如\(m=1\)。容易发现操作1和操作2的顺序不会影响结果,于是可以钦定所有操作1在操作2之前。并且可以发现,进行完所有1后2的次数即为\((\text{连续段个数}-1)\)。然后考虑将\(m>1\)的情况。显然最后序列上每\(m\)长度分一段,则每一段都相......
  • 【FTP】FlashFXP 530 Non-anonymous ... 连接失败(连接已被客户端关闭)
    参考的这个图: ......
  • [CF1098E] Fedya the Potter 题解
    [CF1098E]FedyathePotter题解前言一道类欧好题。题解这道题让求\(c\)数组的中位数,那么有一个比较套路的方法就是二分答案\(mid\)然后计算\(b\)数组中区间和小于\(mid\)的区间个数进行\(check\)。但是\(b\)数组总共有\(\mathcal{O}(n^2)\)项,考虑如何优化。因......
  • [ABC245G] Foreign Friends 题解
    [ABC245G]ForeignFriends题解想法考虑所有颜色相同的弱化版。这种情况下,只需要把所有特殊点都推入队列之后跑多源Dijkstra即可。思路正解与上述做法大致相同。如果有颜色限制,那么可以考虑这个神仙思路:把所有特殊点的颜色用二进制表示,对于每一位,这一位是\(0\)的特殊......
  • CF882E1+CF1882E2 Two Permutations 题解-构造题
    CF882E1+CF1882E2TwoPermutations题解-构造题哇,人类智慧,太智慧了。。。此题作为20231010联考的T3。感觉赛时根本没有去往这方面想。CF1882E1CF1882E2E1是简单版,就是没有要求操作数最小化。E1-EasyVersion方法1首先考虑没有次数限制的,对于单独的每一个串的情况。......
  • [USACO17JAN] Promotion Counting P 题解
    [USACO17JAN]PromotionCountingP题解前言好久没写题解了,今天趁我心情好赶紧水一篇。思路首先拿到这题,关键词检索:子树,比\(p_i\)大的,树状数组!现在考虑如何去掉其他子树的贡献……emm,我直接在算贡献的时候去掉其他子树的贡献不就好了!当然,暴力去贡献复杂度肯定爆炸,这里考虑......
  • [USACO08FEB]meteor Shower S题解(bfs)
    题目描述贝茜听说一场特别的流星雨即将到来:这些流星会撞向地球,并摧毁它们所撞击的任何东西。她为自己的安全感到焦虑,发誓要找到一个安全的地方(一个永远不会被流星摧毁的地方)。如果将牧场放入一个直角坐标系中,贝茜现在的位置是原点,并且,贝茜不能踏上一块被流星砸过的土地。根据预......