Codeforces Round #678 (Div. 2)

A

观察发现, 和顺序无关

int main() {
    IOS;
    for (cin >> _; _; --_) {
        cin >> n >> m; ll sum = 0;
        rep (i, 1, n) cin >> k, sum += k;
        if (sum == m) cout << "YES
";
        else cout << "NO
";
    } 
    return 0;
}

B

简单构造

int main() {
    IOS;
    for (cin >> _; _; --_) {
        cin >> n; memset(a, 0, sizeof a);
        if (n & 1) {
            rep (i, 1, n) a[i][i] = 1, a[i][i + 1] = 4;
            a[n][1] = 4;
        }
        else for (int i = 1; i <= n; i += 2) a[i][i] = a[i][i + 1] = a[i + 1][i] = a[i + 1][i + 1] = 1;
        rep (i, 1, n) {
            rep (j, 1, n) cout << a[i][j] << ' ', a[i][j] = 0;
            cout << '
';
        }
    } 
    return 0;
}

C

按正确的二分走一遍, 找到通过二分比较, 需要多少个 大于 这个数的 和多少个小于这个数的

然后组合数学

int n, m, _, k;
ll inv[N] = {0, 1}, a[N] = {1, 1}, b[N] = {1, 1};
VI fa;

void init(int n, int p = mod) {
    rep (i, 2, n) {
        inv[i] = (ll)(p - p / i) * inv[p % i] % p;
        a[i] = (ll)a[i - 1] * i % p;
        b[i] = (ll)b[i - 1] * inv[i] % p;
    }
}
 
PII work(int k) {
    int l = 1, r = n + 1, x = 0, y = 0;
    while (l < r) {
        int mid = l + r >> 1;
        if (mid <= k) l = mid + 1, ++x;
        else r = mid, ++y;
    }
    return { --x, y };
}
 
int main() {
    IOS; init(1e3);
    cin >> n >> m >> k;
    PII p = work(k + 1);
    ll ans = 0;
    if (n - m - p.se >= 0 && m - 1 - p.fi >= 0 && n - p.se - p.fi - 1 >= 0)
          ans = a[n - m] * b[n - m - p.se] % mod * a[m - 1] % mod * b[m - 1 - p.fi] % mod * a[n - p.se - p.fi - 1] % mod;
    cout << ans << '
';
    return 0;
}

D

题都没读懂, 土匪走的单行道, 居民可以任意走.....原来居民可以任意走啊.....

int main() {
    IOS; cin >> n;
    vector<ll> a(n + 1), siz(n + 1, 1), from(n + 1);
    rep (i, 2, n) cin >> from[i], siz[from[i]] = 0;
    rep (i, 1, n) cin >> a[i];
    ll ans = 0;
    per (i, n, 1) {
        umax(ans, (a[i] - 1 + siz[i]) / siz[i]);
        a[from[i]] += a[i]; siz[from[i]] += siz[i];
    }
    cout << ans;
    return 0;
}

E

找 a[i] 是否可以选入 mex 集

i 左边存在 1~a[i]-1, 或者 x 右边存在 1~a[i]-1, 或者 两边合在一起存在 1~a[i]-1

前两种其实都属于最后一种

最后一种最不好处理, 但我们可以隔空处理, 对于 i 的左右, 我们直接将 i 这个位置转移到 上一次出现 a[i] 的位置 x, 则 x + 1 ~ n就是 i 左右的合集

剩下的就好做了

注意特殊处理 1, 只有在存在 a[i] > 1 的时候 1 才能取到

int h[N], ne[N], a[N], c[N];
bool v[N];

void add(int x, int k) {
    for (; x <= n; x += -x & x) umin(c[x], k);
}

int ask(int x) {
    int ans = n;
    for (; x; x -= -x & x) umin(ans, c[x]);
    return ans;
}

int main() {
    IOS; cin >> n;
    rep (i, 1, n) cin >> a[i], ne[i] = h[a[i]], h[a[i]] = i, c[i] = n;
    rep (i, 1, n) add(i, h[i]);
    rep (i, 2, n + 1) if (ask(i - 1) > h[i]) v[i] = 1;
    per (i, n, 1) {
        add(a[i], ne[i]);
        if (a[i] - 1 && ask(a[i] - 1) > ne[i]) v[a[i]] = 1;
        if (a[i] - 1) v[1] = 1;
    }
    int ans = 0; while (v[++ans]); cout << ans;
    return 0;
}
原文地址:https://www.cnblogs.com/2aptx4869/p/13875668.html