Educational Codeforces Round 3 覆盤
阿新 • • 發佈:2021-10-14
A. USB Driver
腦抽了居然升序排序。。愣了幾秒才發現
一遍 AC。
const int MAXN = 100 + 10; int n, aa[MAXN]; int main() { std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin >> n; int m; cin >> m; rep (i, 1, n) cin >> aa[i]; std::sort(aa + 1, aa + 1 + n, std::greater<int>()); rep (i, 1, n) { aa[i] += aa[i - 1]; if (aa[i] >= m) { cout << i << endl; return 0; } } return 0; }
B. The Best Gift
一遍 AC。
const int MAXN = 2e5 + 10; int n, m, cnt[10 + 1]; int main() { std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin >> n >> m; rep (i, 1, n) { int x; cin >> x; ++cnt[x]; } lli ans = 0; rep (x, 1, 10) { rep (y, x + 1, 10) { ans += cnt[x] * cnt[y]; } } cout << ans << endl; }
C. Load Balancing
直接猜結論:平均分配最優,差至多為 1.
信仰之躍,一遍 AC。
const int MAXN = 1e5 + 10; int n, m; int aa[MAXN]; int bb[MAXN]; int main() { std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin >> n; rep (i, 1, n) cin >> aa[i]; std::sort(aa + 1, aa + 1 + n); int sum = 0; rep (i, 1, n) sum += aa[i]; int avg = sum / n, ext = sum % n; rep (i, 1, n) { bb[i] = avg; if (ext) { ++bb[i], --ext; } } std::sort(bb + 1, bb + 1 + n); lli ans = 0; rep (i, 1, n) ans += std::abs(aa[i] - bb[i]); cout << (ans + 1) / 2 << endl; return 0; }
D. Gadgets for dollars and pounds
場上讀錯題 + 被降智,以為不能二分,無奈跳過了先做 E。
Practice 的時候被二次降智,有個地方沒開 long long 結果爆了,輸出方案也寫爆了,換了題解的方法才過,至今不知道是為什麼。
#錯誤警示:沒開 long long 見祖宗。
const int MAXN = 2e6 + 10;
int n, m, k; lli s;
lli aa[MAXN], bb[MAXN];
int mca[MAXN], mcb[MAXN];
int type[MAXN];
struct IT { int id; lli cost; int day; } dollar[MAXN], pound[MAXN];
lli dls, pds;
bool cmp(IT x, IT y) { return x.cost < y.cost; }
static IT items[MAXN];
bool check(int mid) {
lli cdl = aa[mca[mid]], cpd = bb[mcb[mid]];
// DEBUG(cdl); DEBUG(cpd);
int cnt = 0;
rep (i, 1, dls) items[++cnt] = {dollar[i].id, dollar[i].cost * cdl, mca[mid]};
rep (i, 1, pds) items[++cnt] = {pound[i].id, pound[i].cost * cpd, mcb[mid]};
std::sort(items + 1, items + 1 + cnt, cmp);
lli total = 0;
rep (i, 1, k) {
total += items[i].cost;
// DEBUG(items[i].cost);
}
// DEBUG(total);
return total <= s;
}
int main() {
std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
cin >> n >> m >> k >> s;
rep (i, 1, n) {
cin >> aa[i];
if (i == 1 || aa[mca[i - 1]] > aa[i]) mca[i] = i;
else mca[i] = mca[i - 1];
}
rep (i, 1, n) {
cin >> bb[i];
if (i == 1 || bb[mcb[i - 1]] > bb[i]) mcb[i] = i;
else mcb[i] = mcb[i - 1];
}
rep (i, 1, m) {
int typ, cost; cin >> typ >> cost;
type[i] = typ;
if (typ == 1) dollar[++dls] = {i, cost};
else pound[++pds] = {i, cost};
}
int l = 1, r = n, ans = -1;
while (l <= r) {
int mid = (l + r) >> 1;
if (check(mid)) r = mid - 1, ans = mid;
else l = mid + 1;
}
if (ans == -1) cout << -1 << endl;
else {
check(ans);
cout << ans << endl;
for (int i = 1; i <= k; ++i) {
cout << items[i].id << ' ' << items[i].day <<endl;
}
}
return 0;
}
E. Minimum spanning tree for each edge
學過次小生成樹的人都會做。
交了 3 發才過。第一發是因為沒開 long long,第二發是因為陣列開得太緊了(理論上應該不會溢位啊?但是它確實掛了,我也不知道為什麼)
const int MAXN = 2e5 + 10;
struct E {int v, w;};
struct RE {int u, v, w, chosen, id;} res[MAXN];
bool cmp(RE x, RE y) { return x.w < y.w; }
int n, m;
std::vector<E> G[MAXN];
lli anss[MAXN];
struct DSU {
int fa[MAXN];
int Find(int x) {
return !fa[x] ? x : fa[x] = Find(fa[x]);
}
bool Merge(int x, int y) {
x = Find(x); y = Find(y);
if (x == y) return false;
fa[x] = y; return true;
}
} dsu;
lli kruskal() {
lli ans = 0;
std::sort(res + 1, res + 1 + m, cmp);
int cnt = 0;
rep (i, 1, m) {
if (dsu.Merge(res[i].u, res[i].v)) {
++cnt; ans += res[i].w;
res[i].chosen = true;
}
if (cnt == n - 1) break;
}
return ans;
}
int fa[MAXN][25], mx[MAXN][25];
int dep[MAXN];
const int MXL = 19;
void dfs(int u, int f) {
fa[u][0] = f;
dep[u] = dep[f] + 1;
for (int i = 1; i <= 19; ++i) {
fa[u][i] = fa[fa[u][i - 1]][i - 1];
mx[u][i] = std::max(mx[u][i - 1], mx[fa[u][i - 1]][i - 1]);
}
forall (G[u], i) {
int v = G[u][i].v, w = G[u][i].w;
if (v == fa[u][0]) continue;
mx[v][0] = w;
dfs(v, u);
}
}
int Get(int x, int y) {
if (dep[x] < dep[y]) {
std::swap(x, y);
} int ans = 0;
for (int k = 19, delta = dep[x] - dep[y]; k >= 0; --k) {
if ((delta >> k) & 1) {
ans = std::max(ans, mx[x][k]);
x = fa[x][k];
}
} if (x == y) return ans;
for (int k = 19; k >= 0; --k) {
if (fa[x][k] != fa[y][k]) {
ans = std::max({ans, mx[x][k], mx[y][k]});
x = fa[x][k], y = fa[y][k];
}
}
return std::max({ans, mx[x][0], mx[y][0]});
}
int main() {
std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
cin >> n >> m;
rep (i, 1, m) {
int u, v, w;
cin >> u >> v >> w;
res[i] = {u, v, w, false, i};
}
lli ans = kruskal();
rep (i, 1, m) {
if (res[i].chosen) {
anss[res[i].id] = ans;
G[res[i].u].push_back({res[i].v, res[i].w});
G[res[i].v].push_back({res[i].u, res[i].w});
}
}
dfs(1, 0);
rep (i, 1, m) {
if (res[i].chosen) continue;
int u = res[i].u, v = res[i].v;
lli mxw = Get(u, v);
anss[res[i].id] = ans - mxw + 1ll * res[i].w;
}
rep (i, 1, m) cout << anss[i] << endl;
return 0;
}