赞
踩
给定一个长度为
n
n
n 的数组
a
a
a ,以及一个长度为
n
n
n 的字符串
s
s
s ,字符要么为 'B'
要么为 'R'
。
一次操作中,可以选择一个下标 i i i :
'B'
,可以将
a
i
a_i
ai 减少
1
1
1'R'
,可以将
a
i
a_i
ai 加上
1
1
1执行若干次操作,问是否可以将数组 a a a 操作成一个 1 − n 1-n 1−n 的排列。
对于下标 i i i
'B'
,那么小于等于
a
i
a_i
ai 的值都可以达到
NO
'R'
,那么大于等于
a
i
a_i
ai 的值都可以达到
NO
所以我们最终预处理出每个数可以变成 [ 1 , a i ] [1,a_i] [1,ai] 或者 [ a i , n ] [a_i,n] [ai,n]
贪心的考虑
如果最终我们不能将每个数都拿到,则说明无法操作为一个排列。
时间复杂度: O ( n log n ) O(n\log n) O(nlogn) ,瓶颈在于排序
#include <bits/stdc++.h> using namespace std; void solve() { int n; cin >> n; vector<int> a(n); for (int i = 0; i < n; ++i) cin >> a[i]; string s; cin >> s; vector<int> st, ed; for (int i = 0; i < n; ++i) { if (s[i] == 'B') { if (a[i] <= 0) { cout << "NO\n"; return; } // 1 ~ a[i] st.push_back(a[i]); } else { if (a[i] > n) { cout << "NO\n"; return; } // a[i] ~ n if (a[i] == 1) st.push_back(n); else ed.push_back(a[i]); } } sort(st.begin(), st.end()); sort(ed.begin(), ed.end()); // 先看 st 能拯救多少个 int cur = 1; for (int u: st) { if (u >= cur) cur += 1; else break; } for (int u: ed) { if (u <= cur) cur += 1; else break; } if (cur > n) { cout << "YES\n"; } else { cout << "NO\n"; } } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int T = 1; cin >> T; while (T--) { solve(); } return 0; }
在上述代码实现中,我们做了两部分考虑:
st
中ed
中st
,是否有问题呢?我们来思考下将其加入到 st
和 ed
的情况:
st
,我们优先考虑
a
i
a_i
ai 小的。ed
,我们优先考虑
a
i
a_i
ai 小的。先操作到
[
1
,
a
i
]
[1,a_i]
[1,ai] 的,然后操作
[
a
i
,
n
]
[a_i,n]
[ai,n] ,对于
[
a
i
,
n
]
[a_i,n]
[ai,n] 这部分先考虑
[
1
,
n
]
[1,n]
[1,n] ,再考虑
a
i
>
1
a_i>1
ai>1 的
[
a
i
,
n
]
[a_i,n]
[ai,n] 。因此加入到哪部分都是一样的, [ 1 , n ] [1,n] [1,n] 总是在最中间被操作。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。