【CF】Day48——Codeforces Round 979 (Div. 2) D
D. QED's Favorite Permutation
题目:
思路:
思维题,但是还考实现能力
首先我们要知道什么情况是不能换位置的,为什么时候是需要换位置的
我们先看前一个问题,如果不能换位置,那么肯定是 LR 这样的结构,这样的话L和R中间相当于有一条分界线,此时L左边的数最多只能在左边的区间内移动,R同理
那么什么时候需要换位置呢?显然如果一个数 x 的位置不在数组中的 x 位置时,那么就说明要换了,但是我们肯定还要判断这个数要换到哪里去,同时我们肯定还要考虑到分界线,那我们怎么写比较好呢?
既然L左边的数不可能到R及其之后,那我们就判断L左边有没有数大于等于R不就行了吗?同时这还是一个对称的过程,如果L左边有大于,那么R右边肯定有小于,那我们其实考虑一边即可
所以我们定义一个数组 mx[i] 代表前 i 个元素中的最大元素,那我们先预处理一下mx,然后处理一遍没改变之前有多少个不合法的点,然后在更改的过程中看看改变完之后有没有消除不合法的点或者增加不合法的点,如果有那就是NO,否则YES
代码:
#include <iostream>
#include <algorithm>
#include<cstring>
#include<cctype>
#include<string>
#include <set>
#include <vector>
#include <cmath>
#include <queue>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <stack>
#include <memory>
using namespace std;
#define int long long
#define yes cout << "Yes\n"
#define no cout << "No\n"void solve()
{int n, q;cin >> n >> q;vector<int> p(n+1);vector<int> mx(n+1,0);for (int i = 1; i <= n; i++){cin >> p[i];mx[i] = max(p[i], mx[i - 1]);}string s;cin >> s;s = ' ' + s + ' ';int cnt = 0;for (int i = 1; i <= n; i++){if (s[i] == 'L' && s[i + 1] == 'R' && mx[i] >= i + 1){cnt++;}}for (int i = 0; i < q; i++){int x;cin >> x;if (s[x] == 'L'){//如果之前由隔阂,那么现在就没有了if (s[x+1] == 'R' && mx[x] >= x+1){cnt--;}//如果之前没有,但是现在有了if (s[x-1] == 'L' && mx[x - 1] >= x){cnt++;}s[x] = 'R';}else{//如果之前没有,但是现在有了if (s[x + 1] == 'R' && mx[x] >= x + 1){cnt++;}//如果之前由隔阂,那么现在就没有了if (s[x - 1] == 'L' && mx[x - 1] >= x){cnt--;}s[x] = 'L';}(cnt ? no : yes);}
}signed main()
{cin.tie(0)->sync_with_stdio(false);int t = 1;cin >> t;while (t--){solve();}return 0;
}