Codeforces Round #668 (Div. 2)
总览
A. Permutation Forgery
原数组reverse一下输出。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN = 100 + 10;
int t, n;
int a[MAXN];
int main() {
scanf("%d", &t);
while(t--) {
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
reverse(a+1, a+1+n);
for (int i = 1; i <= n; i++)
printf("%d%c", a[i], i == n ? '
' : ' ');
}
}
B. Array Cancellation
负数前面如果没有足够的正数,就要花硬币消除。否则用前面正数的和抵消一下。
写嗨了数组大小没开够RE了一发。(SB
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN = 1e5 + 10;
int t, n;
LL a[MAXN];
int main() {
scanf("%d", &t);
while(t--) {
scanf("%d", &n);
LL tmp = 0, ans = 0;
for (int i = 1; i <= n; i++) {
scanf("%lld", &a[i]);
if (a[i] >= 0) tmp += a[i];
else {
tmp += a[i];
if (tmp < 0) ans -= tmp, tmp = 0;
}
}
printf("%lld
", ans);
}
}
C. Balanced Bitstring
(s_i)必定要和(s_{i+k})相同。所以直接每隔(k)位看是否同时存在(1)和(0),不存在就把 ? 变成相同的就行了。最后再判一下前k位是否满足题意。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN = 3e5 + 10;
int t, n, k;
char s[MAXN];
bool check() {
int v1, v0;
for (int i = 1; i <= k; i++) {
v0 = v1 = 0;
for (int j = i; j <= n; j += k) {
if (s[j] == '0') v0 = 1;
if (s[j] == '1') v1 = 1;
}
if (v1 && v0) return false;
for (int j = i; j <= n; j += k) {
if (s[j] == '?') {
if (v1) s[j] = '1';
else if (v0) s[j] = '0';
}
}
}
v0 = v1 = 0;
for (int i = 1; i <= k; i++) {
if (s[i] == '0') v0++;
else if (s[i] == '1') v1++;
}
if (v1 > k/2 || v0 > k/2) return false;
return true;
}
int main() {
scanf("%d", &t);
while(t--) {
scanf("%d%d", &n, &k);
scanf("%s", s+1);
printf("%s
", check() ? "YES" : "NO");
}
}
D. Tree Tag
设树的直径为(d)。
考虑以下三种情况。
- 如果开局(dist(a,b) <= da),意味着Bob开局即败。
- 如果(2*da>=d)意味着Alice可以坐镇树的中心,此时Bob必败。
- 如果(2*da>=db)意味着Alice可以追上Bob,此时Bob必败。
如果上面三种情况都不满足,那么Bob必胜。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN = 1e5 + 10;
const LL inf = 0x3f3f3f3f3f3f3f3f;
int t;
int n, a, b, da, db;
vector<int> V[MAXN];
int d[MAXN], v[MAXN], dep[MAXN];
int ans = 0;
void dp(int x) {
v[x] = 1;
for (auto y : V[x]) {
if (v[y]) continue;
dp(y);
ans = max(ans, d[x]+d[y]+1);
d[x] = max(d[x], d[y]+1);
}
}
void dfs(int x, int fa) {
for (auto y : V[x]) {
if (y == fa) continue;
dep[y] = dep[x] + 1;
dfs(y, x);
}
}
int main() {
scanf("%d", &t);
while(t--) {
scanf("%d%d%d%d%d", &n, &a, &b, &da, &db);
for (int i = 1; i <= n; i++) {
d[i] = 0;
v[i] = 0;
dep[i] = 0;
V[i].clear();
}
for (int i = 1; i < n; i++) {
int x, y;
scanf("%d%d", &x, &y);
V[x].push_back(y);
V[y].push_back(x);
}
ans = 0;
dp(1);
dfs(a, 0);
if (da * 2 >= min(ans, db) || dep[b] <= da) printf("Alice
");
else printf("Bob
");
}
}
E. Fixed Point Removal
遍历时,用(sum[i])记录可以被消除的数字个数的前缀和。那么只要(0<=i-a[i]<=sum[i-1]),(a[i])就可以被消除。
再用(d[i])记录着每一个被消除的数字的(i-a[i]),不能被消除记为(inf)。
我们考虑,前面的数字消除会如何影响后面数字呢?一定是让某些原先不可消除的数字变的可消除了。
对于每次询问((x,y)),如何消除前(x)个数字的影响呢?用(sum[i-1])减去(sum[x])就好了。答案即为区间([x+1, n-y])中(d[i] <= sum[i-1]-sum[x])的数字个数。区间内小于(k)的数字个数可以用树状数组或者主席树做。
本题纯属口胡,最后没调出来。可能是错的(QAQ