C2. Adjust The Presentation (Hard Version)
C2. Adjust The Presentation (Hard Version)
This is the hard version of the problem. In the two versions, the constraints on and the time limit are different. In this version, . You can make hacks only if all the versions of the problem are solved.
A team consisting of members, numbered from to , is set to present a slide show at a large meeting. The slide show contains slides.
There is an array of length . Initially, the members are standing in a line in the order of from front to back. The slide show will be presented in order from slide to slide . Each section will be presented by the member at the front of the line. After each slide is presented, you can move the member at the front of the line to any position in the lineup (without changing the order of the rest of the members). For example, suppose the line of members is . After member presents the current slide, you can change the line of members into either , , or .
There is also an array of length . The slide show is considered good if it is possible to make member present slide for all from to under these constraints.
However, your annoying boss wants to make updates to the array . In the -th update, he will choose a slide and a member and set . Note that these updates are persistent, that is changes made to the array will apply when processing future updates.
For each of the states of array , the initial state and after each of the updates, determine if the slideshow is good.
Input
Each test contains multiple test cases. The first line contains the number of test cases (). The description of the test cases follows.
The first line of each test case contains three integers , and (; ) — the number of members and the number of sections.
The second line of each test case contains integers () — the initial order of the members from front to back. It is guaranteed that each integer from to appears exactly once in .
The third line of each test case contains integers () — the members who should present each section.
Each of the next lines contains two integers and (, ) — parameters of an update.
It is guaranteed that the sum of , the sum of and the sum of over all test cases do not exceed respectively.
Output
For each test case, output lines corresponding to the states of the array . Output "YA" if the slide show is good, and "TIDAK" otherwise.
You can output the answer in any case (upper or lower). For example, the strings "yA", "Ya", "ya", and "YA" will be recognized as positive responses.
Example
Input
3
4 2 2
1 2 3 4
1 1
1 2
1 1
3 6 2
1 2 3
1 1 2 3 3 2
3 3
2 2
4 6 2
3 1 4 2
3 1 1 2 3 4
3 4
4 2
Output
YA
TIDAK
YA
YA
TIDAK
YA
TIDAK
YA
YA
Note
For the first test case, you do not need to move the members as both slides are presented by member , who is already at the front of the line. After that, set , now slide must be presented by member which is impossible as member will present slide first. Then, set , the is the same as the initial , making a good presentation possible.
解题思路
当 固定后,要判断其是否是好的,只需从 中依次把第一次出现的数选出来,并判断所构成的序列 是否等于 的前缀即可。例如有 ,,依次选出第一次出现的数就是 ,等于 的前缀,说明是好的。如果 不是 的前缀,说明必定存在最小的位置 使得 ,说明在 中 比 先出现。又因为 中不存在 ,因此 必定会与 中某个位置发生失配。否则 是 的前缀,容易知道存在构造方案使得 是好的。
由于涉及到修改,容易想到维护 ,每次修改相当于令 中某一段循环左移或右移一个单位,非常难维护而且还要判断是否为 的前缀,一开始死磕这种方法做不出来。参考了一下别人的代码,发现实际上维护的是每个值第一次出现的位置。定义 表示在 中值 第一次出现的位置(不存在则设为 ),如果 是 的前缀,说明在 中一定是先出现 ,再出现 ,再出现 以此类推,这等价于 。所以可以用一个变量 统计不满足 的数目,如果 说明 是好的,否则不好。
给 每个值开一个 std::set
存 中出现的位置。当将 修改成 时,因为 和 会改变,其中 表示 中值 的下标,因此受影响的只有 ,, 之间的关系,以及 ,, 之间的关系。在将 改成 的过程中相应地更新 即可,同时还要维护 和 对应的 std::set
。
AC 代码如下,时间复杂度为 :
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 5;
int n, m, k;
int a[N], b[N], p[N];
set<int> st[N];
int f[N], cnt;
void upd(int x, int op) {
if (p[b[x]] - 1 > 0) cnt -= f[p[b[x]] - 1] > f[p[b[x]]];
if (p[b[x]] + 1 <= n) cnt -= f[p[b[x]]] > f[p[b[x]] + 1];
if (op) st[b[x]].insert(x);
else st[b[x]].erase(x);
f[p[b[x]]] = *st[b[x]].begin();
if (p[b[x]] - 1 > 0) cnt += f[p[b[x]] - 1] > f[p[b[x]]];
if (p[b[x]] + 1 <= n) cnt += f[p[b[x]]] > f[p[b[x]] + 1];
}
void solve() {
cin >> n >> m >> k;
for (int i = 1; i <= n; i++) {
cin >> a[i];
p[a[i]] = i;
}
for (int i = 1; i <= n; i++) {
st[i].clear();
st[i].insert(m + 1);
}
for (int i = 1; i <= m; i++) {
cin >> b[i];
st[b[i]].insert(i);
}
for (int i = 1; i <= n; i++) {
f[i] = *st[a[i]].begin();
}
cnt = 0;
for (int i = 1; i < n; i++) {
cnt += f[i] > f[i + 1];
}
cout << (cnt ? "TIDAK" : "YA") << '\n';
while (k--) {
int x, y;
cin >> x >> y;
upd(x, 0);
b[x] = y;
upd(x, 1);
cout << (cnt ? "TIDAK" : "YA") << '\n';
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/18449401
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!
2023-10-06 Python缩进
2022-10-06 Maximum Deletions on a String
2022-10-06 买糖果
2022-10-06 整数拆分