Codeforces Global Round 10 划水记录
文章目录
草,weak pretest,我日他大坝
A
题目描述
给定一个数列,当 $a_i \neq a_{i+1}$ 时,可以合并 $a_i$ 和 $a_{i+1}$,求若干次操作之后的数列的最短长度
简要做法
考虑数列中的最大值 $x$,必然能和某个小的数合成一个更大的数,如此下去最终只剩一个
但是如果全都是同一个数,就不能这样合并,答案就为原序列长度
参考代码
#include <stdio.h>
#include <algorithm>
#include <memory.h>
const int N = 2e5 + 5;
int n, a[N];
int read()
{
int x = 0, f = 1;
char ch = getchar();
while ('0' > ch or ch > '9')
f = ch == '-' ? -1 : 1, ch = getchar();
while ('0' <= ch and ch <= '9')
x = x * 10 + ch - 48, ch = getchar();
return x * f;
}
int main()
{
for (int T = read(); T--;)
{
int n = read();
bool flag = false;
for (int i = 1; i <= n; i++)
{
a[i] = read();
if (a[i] != a[i - 1] and i != 1)
flag = true;
}
printf("%d\n", flag ? 1 : n);
}
return 0;
}
B
题目描述
给你一个数列 $a$,然后每次操作选出最大值 $d$,对于 $1\le i\le n$,把 $a_i$ 换成 $d-a_i$。把这个操作进行 $k$ 次,输出最后的数列。
简要做法
手玩一下样例就知道了,最终答案只会在两种序列中来回变换,判断一下 $k$ 的奇偶性即可
pretest 真 nm weak,连 long long 的数据都没有,然后只有 k 要开 long long,cf 我日你大坝
周巨 快读 + k & 1 在负数的情况下判断奇偶性也不会炸,而用取模会因为负数的原因炸了,奇妙的技巧增加了.jpg
参考代码
#include <stdio.h>
#include <algorithm>
#include <memory.h>
typedef long long ll;
const ll N = 2e5 + 5;
const ll INF = 2147483647;
ll n, k;
ll a[N], b[N], ans[N];
ll read()
{
ll x = 0, f = 1;
char ch = getchar();
while ('0' > ch or ch > '9')
f = ch == '-' ? -1 : 1, ch = getchar();
while ('0' <= ch and ch <= '9')
x = x * 10 + ch - 48, ch = getchar();
return x * f;
}
signed main()
{
for (ll T = read(); T--;)
{
ll d1 = -INF, d2 = -INF;
n = read(), k = read();
for (ll i = 1; i <= n; i++)
a[i] = read(), d1 = std::max(d1, a[i]);
for (ll i = 1; i <= n; i++)
a[i] = d1 - a[i];
for (ll i = 1; i <= n; i++)
d2 = std::max(d2, a[i]);
for (ll i = 1; i <= n; i++)
b[i] = d2 - a[i];
for (ll i = 1; i <= n; i++)
printf("%lld ", k % 2 ? a[i] : b[i]);
puts("");
}
return 0;
}
C
题目描述
给定一个序列,定义一次操作为将一段数全部加 $1$,问将序列变为非严格递增的最小次数。
简要做法
贪心
线性地考虑这个序列,假设我们现在 $[1,i-1]$ 这一段已经非严格递增了,考虑 $i$ 这个位置
假如 $a_{i-1} \leq a_i$,那么 $[1,i]$ 这一段也符合要求了,继续考虑下一位
否则就将 $[1,i-1]$ 这一段不断增加,使得序列符合要求
参考代码
#include <stdio.h>
#include <algorithm>
#include <memory.h>
typedef long long ll;
const ll N = 2e5 + 5;
const ll INF = 2147483647;
ll n, ans;
ll a[N], g[N];
ll read()
{
ll x = 0, f = 1;
char ch = getchar();
while ('0' > ch or ch > '9')
f = ch == '-' ? -1 : 1, ch = getchar();
while ('0' <= ch and ch <= '9')
x = x * 10 + ch - 48, ch = getchar();
return x * f;
}
signed main()
{
for (ll T = read(); T--;)
{
n = read(), ans = 0;
for (int i = 1; i <= n; i++)
a[i] = read();
for (int i = 2; i <= n; i++)
if (a[i] < a[i - 1])
ans += a[i - 1] - a[i];
printf("%lld\n", ans);
}
return 0;
}
D
题目描述
$n$ 个人站成一个环,每个人会攻击左边或右边的人
定义合法状态:
- 如果 $a$ 在攻击 $b$,且 $b$ 只受到 $a$ 的攻击时,$b$ 必须攻击 $a$。
- 如果 $a$ 被旁边两人同时攻击或旁边两人都不攻击他,那么他可以随意选择一个人攻击。
求至少需要改变几个人的攻击方向才能使状态合法
简要做法
一个合法当且仅当不存在 $3$ 个连续的 $L$ 或 $R$
注意特判全 $L$ 或 $R$ 的状态即可
参考代码
#include <stdio.h>
#include <algorithm>
#include <memory.h>
#include <string>
#include <iostream>
#include <math.h>
const int N = 4e5 + 5;
int n;
int a[N];
std::string str;
int read()
{
int x = 0, f = 1;
char ch = getchar();
while ('0' > ch or ch > '9')
f = ch == '-' ? -1 : 1, ch = getchar();
while ('0' <= ch and ch <= '9')
x = x * 10 + ch - 48, ch = getchar();
return x * f;
}
int main()
{
for (int T = read(); T--;)
{
memset(a, 0, sizeof a);
str.clear();
std::cin >> n >> str;
for (int i = 0; i < n; i++)
a[i + 1] = str[i];
bool flag = false;
for (int i = 1; i <= n; i++)
if (i != 1 and a[i] != a[i - 1])
{
flag = true;
break;
}
if (!flag)
printf("%d\n", int(ceil(1.0 * n / 3)));
else
{
int cnt = 0, ans = 0;
int p, q;
for (p = 1; a[p] == a[n]; p++)
;
for (q = n; a[q] == a[1]; q--)
;
ans += (n - q - 1 + p) / 3;
cnt = 0;
for (int i = p; i <= q; i++)
if (a[i] != a[i - 1])
ans += cnt / 3, cnt = 1;
else
cnt++;
ans += cnt / 3;
printf("%d\n", ans);
}
}
return 0;
}