Hello 2023 A-D
Hello 2023 A-D
https://codeforces.com/contest/1779
后面的还没看。感觉晚上脑子不好用了qwq
A. Hall of Fame
LR->RL,修改一个即可覆盖全部
#include <bits/stdc++.h>
using namespace std;
void solve () {
int n;
string s;
cin >> n >> s;
int cnt1 = count (s.begin (), s.end (), 'L'), cnt2 = count (s.begin (), s.end (), 'R');
if (!cnt1 || !cnt2) cout << -1 << endl;
else {
int cnt = 0, ans = 0; //LR->RL
for (int i = 1; i < n; i++) {
if (s[i] == 'R' && s[i-1] == 'L') {
cnt ++;
cout << i << endl;
return ;
}
}
if (cnt) cout << "-1\n";
else cout << "0\n";
}
}
int main () {
int t;
cin >> t;
while (t --) solve ();
}
B. MKnez's ConstructiveForces Task
构造,偶数长度可使总和为 \(0\),奇数长度可使总和为 \(-1\):
\[-1=(\frac n2 + 1)\times(\frac n2 -1) - \frac n2\times\frac n2
\]
#include <bits/stdc++.h>
using namespace std;
void solve () {
int n;
cin >> n;
if (n & 1) {
if (n == 3) cout << "NO\n";
else {
cout << "YES\n";
for (int i = 0; i < n / 2; i++) cout << n / 2 - 1 << ' ' << -1 * n / 2 << ' ';
cout << n / 2 - 1;
cout << endl;
}
}
else {
cout << "YES\n";
for (int i = 0; i < n / 2; i++) cout << "1 -1 ";
cout << endl;
}
}
int main () {
int t;
cin >> t;
while (t --) solve ();
}
C. Least Prefix Sum
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e5 + 5;
int a[N], n, m;
void solve () {
cin >> n >> m;
for (int i = 1; i <= n; i++) cin >> a[i];
if (n == 1) {
cout << 0 << endl;
return ;
}
//从m往两头出发,小于0就修正
int ans = 0, sum = 0;
priority_queue <int, vector<int>, greater<int>> q; //小
for (int i = m + 1; i <= n; i++) {
sum += a[i];
q.push (a[i]);
if (sum < 0) {
auto it = q.top ();
q.pop ();
ans ++;
sum += -2 * it;
}
}
sum = 0;
priority_queue<int> p; //大
for (int i = m; i > 1; i--) {
sum += a[i];
p.push (a[i]);
if (sum > 0) {
auto it = p.top ();
p.pop ();
ans ++;
sum += -2 * it;
}
}
cout << ans << endl;
}
signed main () {
int t;
cin >> t;
while (t --) solve ();
}
//应该贪心改
D. Boris and His Amazing Haircut
首先刀片只能砍的更小,如果存在 \(b[i]>a[i]\) 则一定不可能。
然后如果想一刀切到长度为 \(x\) 的话,两个端点之间不能有大于 \(x\) 的 \(b_i\).
因此可以记录每个 \(b_i\) 的所在位置,然后两两之间查询有无 \(>b_i\) 的值,若无,则可节省一个刀片。
因为有多次查询,所以可以用ST表记录区间最小值
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
int a[N], b[N], n, m;
int f[N][21], Log2[N];
void pre() { // 准备工作,初始化
for (int i = 2; i <= N; ++i) Log2[i] = Log2[i / 2] + 1;
}
void build() {
for (int i = 1; i <= n; i++) f[i][0] = b[i];
for (int i = 1; i <= 20; ++i) {
for (int j = 1; j + (1 << i) - 1 <= n; ++j) {
f[j][i] = max(f[j][i - 1], f[j + (1 << (i - 1))][i - 1]);
}
}
}
int query(int L, int R) {
int len = Log2[R - L + 1];
return max(f[L][len], f[R - (1 << len) + 1][len]);
}
void solve () {
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
for (int i = 1; i <= n; i++) cin >> b[i];
build ();
cin >> m;
map<int, int> cnt;
while (m --) {
int x; cin >> x;
cnt[x] ++;
}
map<int, vector<int>> pos;
for (int i = 1; i <= n; i++) {
if (b[i] > a[i]) {
puts ("NO");
return ;
}
if (b[i] < a[i]) pos[b[i]].push_back (i);
}
//for (auto i = s.rbegin (); i != s.rend (); i++) cout << *i << ": " << L[*i] << ' ' << R[*i] << endl; cout << endl;
for (auto pii : pos) {
vector <int> v = pii.second;
int cur = pii.first, need = v.size ();
for (int i = 1; i < v.size (); i++) {
if (query (v[i-1], v[i]) <= cur) need --; //省下一个刀片
}
if (need > cnt[cur]) {
puts ("NO");
return ;
}
}
puts ("YES");
}
int main () {
ios::sync_with_stdio (0);cin.tie (0);cout.tie (0);
pre ();
int t;
cin >> t;
while (t --) solve ();
}
//ST表查找区间最小值