题目链接:https://codeforces.com/contest/2030/problem/D
题目:
题解:
-
Favotite Permutation即每个数满足i=p[i];此题中,p数组每次询问后保持不变,s根据询问而改变。因此每次需要进行交换的数的位置是相同的,只需要检验s变更后,操作能否满足交换需求与否。故创建需数组need,预处理need,need[i]>0表示p[i]!=i,需要进行交换;创建哈希集合not_ok_pos表示在该位置是交换需求无法满足。
(need数组进行差分处理,因为当需要交换的数中间间隔多个数字时,则要保证左右两个需要的数字及中间数字都能进行交换,即从i->j,need[i]->need[j]都要处理,差分简化操作) -
关于s的操作,当s[i]满足以下条件 s[i]->s[i+1] 或者 s[i]<-s[i-1] 或者 s[i]<->s[i+1]),才能交换,但是前二者,只是单向意愿的满足,若将是s[i]->s[i+1]中是s[i]='R'变为'L'指向左边则不能交换,第二个式子同理。
-
预处理not_ok_pos数组,当最开始输入的操作不能满足需要交换的数的需求时,将该位置添加进哈希表中。
-
处理询问:输入是s中反转的位置,反转当前s[x]会对左右相邻的数可交换性产生影响,故需要根据左右两边是否有需求进行s[i]反转后的操作检验。
- need[x-1]>1,需要操作。反转后,若原来当前位不能交换,即s[x-2]<-s[x-1],s[x]->s[x+1],反转后,是s[x-1]<-s[x],可以交换,满足条件,将x-1从not_ok_pos中删去;若原来当前位置能交换,s[x-1]<-s[x],变为,s[x]->s[x+1],不能交换,将x-1添加到not_ok_pos;
2.与上面同理。
3.若not_ok_pos不为空,即操作后仍然存在怕p[i]!=i,输出NO;为空,输出YES;
- need[x-1]>1,需要操作。反转后,若原来当前位不能交换,即s[x-2]<-s[x-1],s[x]->s[x+1],反转后,是s[x-1]<-s[x],可以交换,满足条件,将x-1从not_ok_pos中删去;若原来当前位置能交换,s[x-1]<-s[x],变为,s[x]->s[x+1],不能交换,将x-1添加到not_ok_pos;
代码如下:
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
#define fi first
#define se second
#define ll long long
#define pii pair<int, int>
bool ok(char l, char r) {
return l == 'R' || r == 'L';
}
int a[N], q, n, need[N];
char s[N];
void solve() {
set<int> not_ok_pos;
vector<pii> v;
for (int i = 1; i <= n; i++) need[i] = 0;
cin >> n >> q;
for (int i = 1; i <= n; i++) {
cin >> a[i];
if (i == a[i]) continue;
int u = i, v = a[i];
if (u > v) swap(u, v);
need[u]++, need[v]--; // 差分
}
for (int i = 1; i <= n; i++) need[i] += need[i - 1];
for (int i = 1; i <= n; i++) cin >> s[i];
for (int i = 1; i < n; i++) {
if (need[i] && !ok(s[i], s[i + 1])) not_ok_pos.insert(i);
}
while (q--) {
int x;
cin >> x;
if (need[x - 1]) {
if (!ok(s[x - 1], s[x])) not_ok_pos.erase(x - 1);
if (ok(s[x - 1], s[x]) && s[x - 1] == 'L') not_ok_pos.insert(x - 1);
}
if (need[x]) {
if (!ok(s[x], s[x + 1])) not_ok_pos.erase(x);
if (ok(s[x], s[x + 1]) && s[x + 1] == 'R') not_ok_pos.insert(x);
}
if (s[x] == 'L')
s[x] = 'R';
else
s[x] = 'L';
if (not_ok_pos.size()) {
cout << "NO" << endl;
} else {
cout << "YES" << endl;
}
}
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t = 1;
cin >> t;
while (t--) { solve(); }
return 0;
}
标签:ok,QED,--,题解,交换,pos,int,need
From: https://www.cnblogs.com/07bit/p/18496616