Codeforces Round #332 (Div. 2)
期末考中途的放松
但好像有点智障...
刚开始不知道能有多种走法...
#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; }
要先判断无效再判断多解...
#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; }
从左到右扫,把遍历的数一个个都删掉,如果当前遇到的最大值-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; }
只考虑 $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; }
不会写啊。。。
就是整一个状压,然后两棵子树合并,合并过程需要符合连边和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; }