# AtCoder Grand Contest 004

## A - Divide a Cuboid

#include <cstdio>

int main() {
long long A, B, C;
scanf("%lld%lld%lld", &A, &B, &C);
if (~A & 1 || ~B & 1 || ~C & 1) puts("0");
else printf("%lld\n", A > B ? A > C ? B * C : A * B : B > C ? A * C : A * B);
return 0;
}


## B - Colorful Slimes

#include <cstdio>
#include <algorithm>

typedef long long LL;
const int MN = 2005;

int N, X, A[MN * 2], B[MN * 2];
LL Ans;

int main() {
scanf("%d%d", &N, &X);
for (int i = 1; i <= N; ++i) {
scanf("%d", &A[i]);
A[N + i] = B[i] = A[i];
Ans += B[i];
}
for (int k = 1; k < N; ++k) {
LL Sum = (LL)k * X;
for (int i = 1; i <= N; ++i) {
B[i] = std::min(B[i], A[N + i - k]);
Sum += B[i];
}
Ans = std::min(Ans, Sum);
}
printf("%lld\n", Ans);
return 0;
}


## C - AND Grid

#include <cstdio>

const int MN = 505;

int N, M;
char A[MN][MN], B[MN][MN], C[MN][MN];

int main() {
scanf("%d%d", &N, &M);
for (int i = 1; i <= N; ++i) {
scanf("%s", A[i] + 1);
for (int j = 1; j <= M; ++j) {
(i & 1 ? B : C)[i][j] = '#';
(i & 1 ? C : B)[i][j] = '.';
}
B[i][1] = C[i][M] = '#';
B[i][M] = C[i][1] = '.';
for (int j = 1; j <= M; ++j)
if (A[i][j] == '#')
B[i][j] = C[i][j] = '#';
}
for (int i = 1; i <= N; ++i) printf("%s\n", B[i] + 1); puts("");
for (int i = 1; i <= N; ++i) printf("%s\n", C[i] + 1);
return 0;
}


## D - Teleporter

#include <cstdio>
#include <algorithm>
#include <vector>

const int MN = 100005;

int N, K, A[MN], Ans;
std::vector<int> G[MN];

int dep[MN], kpar[MN], per[MN], stk[MN], tp;
void DFS(int u) {
stk[++tp] = u;
if (dep[u] > K) kpar[u] = stk[tp - K + 1];
for (int v : G[u]) dep[v] = dep[u] + 1, DFS(v);
--tp;
}

int del[MN];
void Del(int u) {
del[u] = 1;
for (int v : G[u]) if (!del[v]) Del(v);
}

int main() {
scanf("%d%d", &N, &K);
for (int i = 1; i <= N; ++i) scanf("%d", &A[i]);
if (A[1] != 1) A[1] = 1, Ans = 1;
for (int i = 2; i <= N; ++i) G[A[i]].push_back(i);
DFS(1);
for (int i = 1; i <= N; ++i) per[i] = i;
std::sort(per + 1, per + N + 1, [](int i, int j) { return dep[i] > dep[j]; });
for (int i = 1; i <= N; ++i) if (kpar[per[i]] && !del[per[i]]) ++Ans, Del(kpar[per[i]]);
printf("%d\n", Ans);
return 0;
}


## E - Salvage Robots

DP 转移使用前缀和优化一下，最终答案就是黄色矩形变成整个大矩形时的 DP 值，时间复杂度为 $\mathcal O (N^4)$，数组可以滚动掉一维。

#include <cstdio>
#include <algorithm>

const int MN = 105;

int N, M, px, py, A[MN][MN], B[MN][MN], C[MN][MN];
char s[MN][MN];

int f[MN][MN][MN];

int main() {
scanf("%d%d", &N, &M);
for (int i = 1; i <= N; ++i) {
scanf("%s", s[i] + 1);
for (int j = 1; j <= M; ++j) {
A[i][j] = s[i][j] == 'o';
B[i][j] = B[i][j - 1] + A[i][j];
C[i][j] = C[i - 1][j] + A[i][j];
if (s[i][j] == 'E') px = i, py = j;
}
}
for (int u = 0; u <= px - 1; ++u) {
for (int d = 0; d <= N - px; ++d) {
for (int l = 0; l <= py - 1; ++l) {
for (int r = 0; r <= M - py; ++r) {
int tu = std::max(px - u, 1 + d);
int td = std::min(px + d, N - u);
int tl = std::max(py - l, 1 + r);
int tr = std::min(py + r, M - l);
if (u && px - u == tu && tl <= tr) f[d][l][r] += B[px - u][tr] - B[px - u][tl - 1];
if (d) f[d][l][r] = std::max(f[d][l][r], f[d - 1][l][r] + (px + d == td && tl <= tr ? B[px + d][tr] - B[px + d][tl - 1] : 0));
if (l) f[d][l][r] = std::max(f[d][l][r], f[d][l - 1][r] + (py - l == tl && tu <= td ? C[td][py - l] - C[tu - 1][py - l] : 0));
if (r) f[d][l][r] = std::max(f[d][l][r], f[d][l][r - 1] + (py + r == tr && tu <= td ? C[td][py + r] - C[tu - 1][py + r] : 0));
}
}
}
}
printf("%d\n", f[N - px][py - 1][M - py]);
return 0;
}


## F - Namori

$N$ 是奇数时直接输出 $-1$。下文默认 $N$ 为偶数。

（注意到那个结论甚至没有提到棋子不能重叠之类的问题）

#include <cstdio>
#include <algorithm>
#include <vector>

typedef long long LL;
const int MN = 100005;

int N, M;
std::vector<int> G[MN];

int a, b, vis[MN], par[MN], dep[MN], num1[MN], num2[MN], kval[MN];
void DFS(int u, int fr) {
vis[u] = 1;
dep[u] = dep[par[u] = fr] + 1;
num1[u] = dep[u] & 1;
num2[u] = ~dep[u] & 1;
for (int v : G[u]) if (v != fr) {
if (!vis[v]) DFS(v, u), num1[u] += num1[v], num2[u] += num2[v];
else a = u, b = v;
}
}

int main() {
scanf("%d%d", &N, &M);
if (N & 1) return puts("-1"), 0;
for (int i = 1; i <= M; ++i) {
int x, y;
scanf("%d%d", &x, &y);
G[x].push_back(y);
G[y].push_back(x);
}
DFS(1, 0);
if (M == N - 1) {
if (num1[1] != num2[1]) return puts("-1"), 0;
LL Ans = 0;
for (int i = 2; i <= N; ++i) {
int x = num2[i] - num1[i];
Ans += x < 0 ? -x : x;
}
printf("%lld\n", Ans);
} else {
if ((dep[a] ^ dep[b]) & 1) {
if (num1[1] != num2[1]) return puts("-1"), 0;
for (int x = a; x; x = par[x]) ++kval[x];
for (int x = b; x; x = par[x]) --kval[x];
LL Ans = 0;
static int seq[MN], cnt;
seq[cnt = 1] = 0;
for (int i = 2; i <= N; ++i) {
if (!kval[i]) {
int x = num2[i] - num1[i];
Ans += x < 0 ? -x : x;
} else
seq[++cnt] = kval[i] * (num2[i] - num1[i]);
}
std::sort(seq + 1, seq + cnt + 1);
int mid = seq[cnt / 2 + 1];
for (int i = 1; i <= cnt; ++i)
Ans += seq[i] < mid ? mid - seq[i] : seq[i] - mid;
printf("%lld\n", Ans);
} else {
int k = N / 2 - num1[1];
for (int x = a; x; x = par[x]) num1[x] += k;
for (int x = b; x; x = par[x]) num1[x] += k;
LL Ans = 0;
for (int i = 2; i <= N; ++i) {
int x = num2[i] - num1[i];
Ans += x < 0 ? -x : x;
}
printf("%lld\n", Ans + (k < 0 ? -k : k));
}
}
return 0;
}

posted @ 2020-06-13 03:51  粉兔  阅读(57)  评论(0编辑  收藏