Codeforces #670 div2
A
水题,直接模拟能填就填。
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
typedef long long ll;
const ll MAXN = 1e6+10;
ll N, M, T, t[MAXN];
int main() {
scanf("%lld", &T);
while (T--) {
for (ll i = 0; i <= 100; i++) t[i] = 0;
scanf("%lld", &N);
for (ll tem, i = 1; i <= N; i++) {
scanf("%lld", &tem);
t[tem]++;
}
ll ans = 0;
for (ll i = 0; i <= 100; i++) {
if (t[i]) {
t[i]--;
} else {
ans += i;
break;
}
}
for (ll i = 0; i <= 100; i++) {
if (t[i]) {
t[i]--;
} else {
ans += i;
break;
}
}
printf("%lld\n", ans);
}
return 0;
}
B
先排序,然后 前5个,前4个后1个,前3个后2个,前2个后3个,前1个后4个,后5个 六种方案取max就行。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
typedef long long ll;
const ll MAXN = 1e6+10;
const ll INF = 0x3f3f3f3f3f3f3f3f;
ll N, T, val[MAXN];
ll Max();
int main() {
scanf("%lld", &T);
while (T--) {
scanf("%lld", &N);
for (ll i = 1; i <= N; i++) {
scanf("%lld", val+i);
}
sort(val+1, val+N+1);
ll ans = Max();
printf("%lld\n", ans);
}
return 0;
}
ll Max() {
ll ret = -INF;
ret = max(val[1] * val[2] * val[3] * val[4] * val[5], ret);
ret = max(val[1] * val[2] * val[3] * val[4] * val[N], ret);
ret = max(val[1] * val[2] * val[3] * val[N-1] * val[N], ret);
ret = max(val[1] * val[2] * val[N-2] * val[N-1] * val[N], ret);
ret = max(val[1] * val[N-3] * val[N-2] * val[N-1] * val[N], ret);
ret = max(val[N-4] * val[N-3] * val[N-2] * val[N-1] * val[N], ret);
return ret;
}
C
直接找到重心,如果只有一个随便输出一条边两次就行。
否则在一个重心的子树切一根然后接到另一个重心上。
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
typedef long long ll;
const ll MAXN = 1e6+10;
struct edge {
ll nt, to;
} E[MAXN];
ll N, M, T, cnt = -1, head[MAXN], siz[MAXN], fa[MAXN], w[MAXN];
ll root, other, del;
void add(ll, ll);
void dfs(ll, ll);
ll gtl(ll);
int main() {
scanf("%lld", &T);
while (T--) {
scanf("%lld", &N);
root = 0, del = 0, other = 0;
for (ll i = 1; i <= N; i++) {
head[i] = -1;
siz[i] = 0;
w[i] = 0;
fa[i] = 0;
}
cnt = -1;
ll tem1, tem2;
for (ll x, y, i = 1; i < N; i++) {
scanf("%lld%lld", &x, &y);
add(x, y);
add(y, x);
tem1 = x, tem2 = y;
}
dfs(1, 0);
if (!other) {
printf("%lld %lld\n", tem1, tem2);
printf("%lld %lld\n", tem1, tem2);
} else {
if (fa[other] == root) swap(root, other);
ll del = gtl(root);
printf("%lld %lld\n", del, fa[del]);
printf("%lld %lld\n", del, other);
}
}
return 0;
}
ll gtl(ll n) {
bool flag = 0;
for (ll i = head[n]; ~i; i = E[i].nt) {
ll v = E[i].to;
if (v == fa[n]) continue;
else {
return gtl(v);
flag = 1;
}
}
if (!flag) return n;
}
void dfs(ll n, ll ff) {
fa[n] = ff;
for (ll i = head[n]; ~i; i = E[i].nt) {
ll v = E[i].to;
if (v == ff) continue;
else {
dfs(v, n);
siz[n] += siz[v];
w[n] = max(w[n], siz[v]);
}
}
siz[n]++;
w[n] = max(w[n], N - siz[n]);
if (root == 0 || w[root] > w[n]) root = n, other = 0;
else if (w[root] == w[n]) other = n;
}
void add(ll x, ll y) {
cnt++;
E[cnt].to = y;
E[cnt].nt = head[x];
head[x] = cnt;
}
/*
1
5
1 2
2 3
3 4
2 5
18
1 2
1 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
2 11
11 12
11 13
2 14
14 15
2 16
16 18
16 17
*/
D
先差分,然后我们可以知道序列的最大值一定是 \(b_n\) 或者 \(c_1\) 那么我们就让这俩最接近就好。
那么我们可以考虑
当 \(a_i > a_{i-1}\) 令 \(b_{i} = b_{i-1} + a_i - a_{i-1}\)
当 \(a_i < a_{i-1}\) 令 \(c_{i} = c_{i-1} + a_i - a_{i-1}\)
那么我们令 \(K = \sum_{i=2}^N \max(a_i - a_{i-1}, 0)\) 令 \(c_1 = x\)
那么 原题即为求解 \(\max(x, a_1-x+K)\)
那么我们令 \(x\) 与 \(a_1-x+K\) 尽可能接近即可。
答案即为 \(\lceil \frac{a_1+K}{2} \rceil\)
对于一个修改,我们发现只会修改到 \(a_l-a_{l-1}\) 和 \(a_{r+1} - a_r\) 的值
那么只需要在相应的位置修改并将影响加至 \(K\) 即可。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
typedef long long ll;
const ll MAXN = 1e6+10;
ll N, M, T, val[MAXN], del[MAXN], sum;
ll ans(ll);
void upd(ll, ll);
int main() {
scanf("%lld", &N);
for (ll i = 1; i <= N; i++) {
scanf("%lld", val+i);
del[i] = val[i] - val[i-1];
if (i != 1 && del[i] > 0) sum += del[i];
}
printf("%lld\n", ans(val[1] + sum));
scanf("%lld", &M);
for (ll i = 1, l, r, d; i <= M; i++) {
scanf("%lld%lld%lld", &l, &r, &d);
if (l == 1) val[1] += d;
else {
upd(l, d);
}
if (r != N) {
upd(r+1, -d);
}
printf("%lld\n", ans(val[1] + sum));
}
return 0;
}
void upd(ll pos, ll v) {
ll bef = max(del[pos], 0LL);
del[pos] += v;
sum += max(del[pos], 0LL) - bef;
}
ll ans(ll x) {
if (x >= 0) return (x + 1) / 2;
else return x / 2;
}
希望我们都有一个光明的未来