Educational Codeforces Round 3 复盘

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;
}

上一篇:vault应用例子(禁止sys用户访问其他用户下的表)


下一篇:Scala方法中if的返回值