Loading

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 to gac (by swapping a and g) or acg (by swapping g and c).

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;
}
posted @ 2020-10-19 11:12  —O0oO-  阅读(287)  评论(0编辑  收藏  举报