Codeforces Round #668 (Div. 2)

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 ?  '\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\n", 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\n", 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\n");
            else printf("Bob\n");
    }
}

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

posted @ 2020-09-07 01:38  jvruodejrLS  阅读(247)  评论(0编辑  收藏  举报

Contact with me