嘘~ 正在从服务器偷取页面 . . .

UOJ180 【UR #12】实验室外的攻防战 题解


UOJ180 【UR #12】实验室外的攻防战 题解

题目链接:#180. 【UR #12】实验室外的攻防战

题意

经过跳蚤侦察兵的勘察,跳蚤国王发现Picks博士的防御工事有着 $n$ 处薄弱点,于是他把他的跳蚤大军分成了 $n$ 支小队,并打算让它们分别进攻每一个薄弱点。但是因为战场混乱,这 $n$ 支小队的位置被打乱了,重新整队之后,跳蚤国王发现第 $i$ 个位置的小队编号为 $A_i$(显然 $A$ 是一个排列)。

经过计算,跳蚤国王发现,让第 $i$ 个位置的小队编号为 $B_i$ 时,他的军队可以发挥出最大的战斗力(保证 $B$ 也是一个排列)。

跳蚤国王可以发出指令来改变小队们的排列顺序。每一次,他都会报出一个整数 $i~(1 \leq i < n)$。如果排在第 $i$ 个位置的小队编号大于第 $i+1$ 个位置的小队,那么这两支小队会交换顺序,否则这个命令将会被忽略。

现在跳蚤国王希望他的军队能够发挥出最强大的战斗力,于是他想要知道是否存在一种指令序列,使得小队们可以按照排列 $B$ 的方式排列。

但是因为小队数目实在是太多,跳蚤国王一时间也没有看出答案。于是他派跳蚤绑架来了你——这附近最著名的民间科学家来帮他计算这个问题的答案。

输入格式

第一行包含一个正整数 $n~(n \leq 10^5)$。

接下来两行,每行 $n$ 个正整数,分别描述排列 $A$ 和排列 $B$。

输出格式

对于每组数据,如果存在这样的指令序列,输出 “YES”,否则输出 “NO”(请注意大小写)。

注意到如果两个数 $u < v$ 在 $A$ 中满足 $u$ 在 $v$ 的左边,

因为只能交换相邻的两个,任意试图将 $u$ 换到 $v$ 右侧的操作都要经过 $v$ ,所以 $u$ 始终在 $v$ 的左侧。

可以证明,当且仅当不存在任意一对 $u < v$ ,

满足 $A$ 中 $u$ 在 $v$ 左侧而 $B$ 中 $v$ 在 $u$ 右侧时,原序列一定存在合法的解。

证明 设 $n$ 元置换 $\varphi$ 满足 $\varphi(b_i)=i$ 。

记序列 $A’ = \{\varphi(a_1),\varphi(a_2),\cdots,\varphi(a_n)\}$ 。

考虑对 $A’$ 冒泡排序,使其变为 $B’=\{\varphi(b_1),\varphi(b_2),\cdots,\varphi(b_n)\} = \{1,2,\cdots ,n\}$

考察每次交换,设交换了 $u,v$ ($u$ 在 $v$ 左侧),则在 $A’$ 中为 $\varphi(u),\varphi(v)$ 且 $\varphi(u) > \varphi(v)$

由 $\varphi(u) > \varphi(v)$ 以及 $\varphi$ 的定义可知,在 $B$ 中,$u$ 在 $v$ 的右边。

由条件可知 $u > v$ (否则矛盾)可知这一次交换可以成功进行,进而每次均可行。$\square$

于是我们只需要判断是否存在这样的 $u < v$ 即可。

记 $p_{a_i} = i, q_{b_i} = i$ ,则问题转化为判断是否存在 $u < v$ 满足 $p_u < p_v \, \land \, q_u > q_v$ 。

这就是一个二维数点问题。考虑固定 $v$ ,用树状数组维护 $[1,p_v)$ 的前缀 $q$ 最大值即可。

时间复杂度 $\mathcal{O}(n \log n)$

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
void up(int &x, int y) { x < y ? x = y : 0; }
void down(int &x, int y) { x > y ? x = y : 0; }
#define lowbit(x) ((x) & (-(x)))
#define rep(i, a, b) for(int i = (a), i##END = (b); i <= i##END; i++)
#define Rep(i, a, b) for(int i = (a), i##END = (b); i >= i##END; i--)
#define N ((int)(1e5 + 15))

int n, a[N], b[N], tr[N];
void add(int x, int v) { for(int i = x; i <= n; i += lowbit(i)) up(tr[i], v); }
int qry(int x, int r = 0) { for(int i = x; i; i -= lowbit(i)) up(r, tr[i]); return r; }
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    // freopen("check.in","r",stdin);
    // freopen("check.out","w",stdout);
    cin >> n; int x;
    rep(i, 1, n) { cin >> x; a[x] = i; }
    rep(i, 1, n) { cin >> x; b[x] = i; }
    for(int i = 1; i <= n; add(a[i], b[i]), i++)
        if(qry(a[i]) > b[i]) return cout << "NO\n", 0;
    return cout << "YES\n", 0;
}

参考文献

[1] https://yhx-12243.github.io/OI-transit/records/uoj180.html


文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录