AGC048
我觉得思维题其实真的很重要
AGC048
1200才计rating,虽然我打的也很菜。
我感觉atcoder的分比较实,希望寒假把 atcoder也打上去
A - atcoder < S
Given is a string \(S\) consisting of lowercase English letters. Snuke can do the operation of swapping two adjacent characters in SS. For example, if \(S\) ==
agc
, one operation can change it togac
(by swappinga
andg
) oracg
(by swappingg
andc
).Snuke wants to do this operation zero or more times so that
atcoder
< \(S\) holds lexicographically.Determine whether the objective is achievable. If it is achievable, find the minimum number of operations needed.
错误的思路:
for _ in range(int(input())):
s = input()
ans = -1
for i in range(len(s)):
if s[i] != 'a':
ans = i
break
print(ans)
B-Bracket Score
开始的时候一直想着怎么遍历全部的括号组合。
后来意识到应该从 \(A\) ,\(B\) 去入手
假定最先全部选择 \(A\)
然后 \(B_i = B_i - A_i\)
问题就转化成了在新的数组 \(B\) 里选择一对一对的括号使得和最大。
每次选择 \(B_i\) 和 \(B_j\) 必须有 \(j-i+1\) 是偶数
后面发现好像可以随便选
关于这点比较玄学, 我发现只要选择了一样多的偶数和奇数,总是能找到一种方式让他们是合法的括号序列,目前还没有想到怎么证明这个的正确性
于是就分成奇数和偶数
排个序,一直选
int main(){
cin >> n;
long long ans = 0;
for(int i = 1;i <= n;i++)cin >> A[i],ans += A[i];
for(int i = 1;i <= n;i++)cin >> B[i],B[i] -= A[i];
vector<int>a,b;
for(int i = 1;i <= n;i++){
if(i & 1)a.push_back(B[i]);
else b.push_back(B[i]);
}
sort(a.begin(),a.end(),greater<int>());
sort(b.begin(),b.end(),greater<int>());
for(int i = 1;i <= n/2;i++){
if(a[i-1] + b[i-1] > 0){
ans += a[i-1] + b[i-1];
}
}
cout << ans << endl;
}
C-Penguin Skating
说实话这个游戏我好像在哪玩过...
或者自己之前脑子里想过这个游戏
但还是没有 A 出来
样例二大概就是这么个情况
假策略:
先对AB排序
然后从前往后扫
若
A[i] == B[i]
则跳过若
A[i] > B[i]
,则看
B[i]-1
的位置有没有🐧或墙,或则第i-1
只🐧 没移动之前 是否在B[i]-1
的位置(可以先借用第i-1
只🐧当墙,然后第i-1
只再归位)例如
O O O X X X 否则无解
若
A[i] < B[i]
往后面扫,若
A[i+p] - p == B[i]
则把p
个全部往后推否则无解
O O O O X X X X #include<bits/stdc++.h> using namespace std; const int N = 2e5 + 10; int A[N], B[N], n, k; int main() { cin >> n >> k; A[0] = 0; B[0] = 0; A[n + 1] = k + 1; B[n + 1] = k + 1; for (int i = 1; i <= n; i++)cin >> A[i]; for (int i = 1; i <= n; i++)cin >> B[i]; sort(A, A + 2 + n); sort(B, B + 2 + n); int ans = 0; int pre = 0; for (int i = 1; i < n + 2; i++) { int now = A[i]; if (A[i] > B[i]) { if (pre + 1 == B[i] or A[i - 1] + 1 == B[i]) { ans++; A[i] = B[i]; } else { cout << -1 << endl; return 0; } } else if (A[i] < B[i]) { int f = 0; int p; for (p = 1; i + p < n + 2; p++) { if (A[i + p] - p == B[i]) { f = 1; break; } } if (f) { for (int j = 0; j < p; j++) { A[i + j] = B[i] + j; } ans += p; } else { cout << -1 << endl; return 0; } } pre = now; } cout << ans << endl; }
正解
考虑🐧之间的空方块, \(x_0,....,x_n\)
每次操作就是 \(x_i := 0 ,\ x_{i+1} += x_i\)
实在是妙
/*
* @Author: zhl
* @Date: 2020-10-19 10:49:39
*/
#include<bits/stdc++.h>
#define max(a,b) (a>b?a:b)
#define int long long
using namespace std;
const int N = 1e5 + 10;
int A[N], B[N];
int n, k;
signed main() {
cin >> n >> k;
A[n + 1] = B[n + 1] = k + 1;
for (int i = 1; i <= n; i++)cin >> A[i];
for (int i = 1; i <= n; i++)cin >> B[i];
for (int i = n + 1; i >= 1; i--) {
A[i] = A[i] - A[i - 1] - 1;
B[i] = B[i] - B[i - 1] - 1;
}
int ans = 0;
int j = 1;
for (int i = 1; i <= n + 1; i++) {
if (!B[i])continue;
while (!A[j])j++;
int sum = 0; int st = j;
while (sum < B[i] and j <= n + 1)sum += A[j++];
if (sum != B[i]) {
puts("-1"); return 0;
}
int ed = j - 1;
ans += max(0, i - st) + max(0, ed - i);
}
cout << ans << endl;
}