Codeforces Round #332 (Div. 2)

 

期末考中途的放松

但好像有点智障...

A. Patrick and Shopping

刚开始不知道能有多种走法...

#include <bits/stdc++.h>

int main() {
    int a, b, c;
    scanf("%d%d%d", &a, &b, &c);
    int sum1 = a + b + c;
    int sum2 = 2 * a + 2 * b;
    sum1 = std::min(sum1, a + c + c + a);
    sum2 = std::min(sum2, b + c + c + b);
    printf("%d\n", std::min(sum1, sum2));
    return 0;
}
View Code

 

B. Spongebob and Joke

要先判断无效再判断多解...

#include <bits/stdc++.h>

const int N = 1e5 + 7;
int f[N], b[N], a[N];
std::vector<int> pos[N];

int main() {
    int n, m;
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++)
        scanf("%d", f + i), pos[f[i]].push_back(i);
    for (int i = 1; i <= m; i++)
        scanf("%d", b + i);
    int ans0 = 0, ans2 = 0;
    for (int i = 1; i <= m; i++) {
        if (pos[b[i]].empty()) {
            ans0 = 1;
            continue;
        }
        if (pos[b[i]].size() > 1) {
            ans2 = 1;
            continue;
        }
        a[i] = pos[b[i]].back();
    }
    if (ans0) puts("Impossible");
    else if (ans2) puts("Ambiguity");
    else {
        puts("Possible");
        for (int i = 1; i <= m; i++)
            printf("%d%c", a[i], " \n"[i == m]);
    }
    return 0;
}
View Code

 

C. Day at the Beach

从左到右扫,把遍历的数一个个都删掉,如果当前遇到的最大值-1的数在后面都没有出现了,那么就可以在这里分割一下。

#include <bits/stdc++.h>

const int N = 1e5 + 7;

int h[N], n, v[N], tol;

struct BIt {
    int tree[N];
    inline int lowbit(int x) {
        return x & -x;
    }
    void add(int x, int v) {
        for (int i = x; i <= tol; i += lowbit(i))
            tree[i] += v;
    }
    int query(int x) {
        int ans = 0;
        for (int i = x; i; i -= lowbit(i))
            ans += tree[i];
        return ans;
    }
} bit;

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
        scanf("%d", h + i), v[i] = h[i];
    std::sort(v + 1, v + 1 + n);
    tol = std::unique(v + 1, v + 1 + n) - v - 1;
    for (int i = 1; i <= n; i++) {
        h[i] = std::lower_bound(v + 1, v + 1 + tol, h[i]) - v;
        bit.add(h[i], 1);
    }
    int cur = 1;
    int ans = 0;
    for (int i = 1; i <= n; i++) {
        cur = std::max(cur, h[i]);
        bit.add(h[i], -1);
        if (cur > tol || (cur <= tol && !bit.query(cur - 1))) ans++;
        while (cur <= tol && !bit.query(cur)) cur++;
        //printf("ans = %d cur = %d\n", ans, cur);
    }
    printf("%d\n", ans);
    return 0;
}
View Code

 

D. Spongebob and Squares

只考虑 $n < m$ 的情况

得到 $n$ 项答案的组成

要组成长度为 $i$ 的正方形,那么有 $(n- i - 1)(m-i - 1)$ 个

即为 $\sum \limits_{i=1}^{n} (n-i-1)(m-i-1)=x$

得到 $n^2m-(n+m)\text{sum1}(n-1)+\text{sum2}(n-1) = x$ 

发现是三次方的量级,所以 $n$ 从 $1$ 到 $\sqrt[3]x$ 枚举即可。

#include <bits/stdc++.h>
#define int long long
#define pii pair<int, int>

std::vector<std::pii> p;
int ans;

int sum2(int x) {
    return x * (x + 1) * (2 * x + 1) / 6;
}

int sum1(int x) {
    return x * (x + 1) / 2;
}

signed main() {
    int x;
    scanf("%lld", &x);
    int maxn = std::min((int)(pow(x, 1.0 / 3) * 10), x);
    for (int n = 1; n <= maxn; n++) {
        int you = x + n * sum1(n - 1) - sum2(n - 1);
        int zuo = n * n - sum1(n - 1);
        int m = you / zuo;
        if (n > m) break;
        if (you % zuo == 0 && m > 0) {
            p.push_back(std::pii(n, m));
            if (n != m)
                p.push_back(std::pii(m, n));
        }
    }
    std::sort(p.begin(), p.end());
    p.erase(std::unique(p.begin(), p.end()), p.end());
    printf("%d\n", (signed)p.size());
    for (int i = 0; i < p.size(); i++)
        printf("%lld %lld\n", p[i].first, p[i].second);
    return 0;
}
View Code

 

E. Sandy and Nuts

不会写啊。。。

就是整一个状压,然后两棵子树合并,合并过程需要符合连边和LCA的关系。把连边和LCA都作为判断是否符合的条件。

刚开始还想着先把连边关系建好直接做LCA部分。。。

#include <bits/stdc++.h>
#define ll long long

const int N = 14;
ll d[1 << N][N];
bool mp[N][N];
int a[N * 10], b[N * 10], c[N * 10], n, m, q;

bool in(int u, int S) {
    return S >> u & 1;
}

ll solve(int S, int u) {
    ll &ans = d[S][u];
    if (ans != -1) return ans;
    ans = 0;
    int cur_state = S - (1 << u);
    int v;
    for (int i = 0; i < n; i++) 
        if (in(i, cur_state)) {
            v = i;
            break;
        }
    for (int s0 = cur_state; s0; s0 = (s0 - 1) & cur_state) if (in(v, s0)) {
        bool flag = 1;
        for (int i = 0; i < n; i++) if (i != u) {
            if (!flag) break;
            for (int j = 0; j < n; j++) if (j != u)
                if (mp[i][j] && (in(i, s0) ^ in(j, s0))) {
                    flag = 0;
                    break;
                }
        }
        if (!flag) continue;
        int vv, cnt = 0;
        for (int i = 0; i < n; i++) {
            if (mp[u][i] && in(i, s0)) {
                vv = i, cnt++;
            }
        }
        if (cnt >= 2) continue;
        for (int i = 1; i <= q; i++) {
            if (c[i] == u && in(a[i], s0) && in(b[i], s0)) {
                flag = 0;
                break;
            }
            if (in(c[i], s0) && (!in(a[i], s0) || !in(b[i], s0))) {
                flag = 0;
                break;
            } 
        }
        if (!flag) continue;
        if (cnt == 1) {
            ans += solve(S - s0, u) * solve(s0, vv);
        } else {
            for (int i = 0; i < n; i++) if (in(i, s0))
                ans += solve(S - s0, u) * solve(s0, i);
        }
    }
    return ans;
}

int main() {
    memset(d, -1, sizeof(d));
    scanf("%d%d%d", &n, &m, &q);
    for (int i = 1; i <= m; i++) {
        int u, v;
        scanf("%d%d", &u, &v);
        u--, v--;
        mp[u][v] = mp[v][u] = 1;
    }
    for (int i = 1; i <= q; i++)
        scanf("%d%d%d", a + i, b + i, c + i), a[i]--, b[i]--, c[i]--;
    for (int i = 0; i < n; i++)
        d[1 << i][i] = 1;
    ll ans = solve((1 << n) - 1, 0);
    printf("%lld\n", ans);
    //printf("%d\n", solve((1 << n) - 1, 0));
    return 0;
}
View Code
posted @ 2019-12-31 19:35  Mrzdtz220  阅读(157)  评论(0编辑  收藏  举报