YBTOJ 贪心算法合集

奶牛晒衣服

开个堆,记录个时间,每次抠出来堆顶减去 b 再扔回去就做完了。

read(n, a, b);
rep(i, 1, n) read(h[i]);
priority_queue<int> q;
rep(i, 1, n) q.push(h[i]);
int t = 0;
while (q.top() > t * a) {
    t++;
    int x = q.top();
    q.pop();
    // printf("x=%d\n",x);
    x -= b;
    q.push(x);
}
printf("%d", t);

雷达装置

对于每个建筑物,解方程找出能探测到他的最左和最右端点,问题转化为最小区间点覆盖问题。

按 右 端 点 排 序! ! !

按 右 端 点 排 序! ! !

按 右 端 点 排 序! ! !

畜栏预定

按左端点排序,依次扔到堆里,堆里按右端点开小根堆,然后贪心即可。

荷马史诗

哈夫曼树模板。
因为哈夫曼树是从底层往根建的,所以首先你要把他补成一颗完全 k 叉树,这样保证了最优性质。

#define int long long

struct qwq {
    int h, w;
    bool operator<(const qwq &x) const {
        if (w == x.w)
            return h > x.h;
        return w > x.w;
    }
};
priority_queue<qwq> q;
int n, k;
signed main() {
    read(n, k);
    rep(i, 1, n) {
        int x;
        read(x);
        q.push({ 1, x });
    }
    while ((q.size() - 1) % (k - 1)) q.push({ 1, 0 });
    int ans = 0;
    while (q.size() >= k) {
        int w = 0, h = -1;
        rep(i, 1, k) {
            auto it = q.top();
            q.pop();
            w += it.w;
            h = max(h, it.h);
        }
        ans += w;
        q.push({ h + 1, w });
    }
    printf("%lld\n%lld", ans, q.top().h - 1);
}

排队接水

贪心的想,慢的人往后扔,一定最优,一遍sort即可。

砍树问题

题面很丑陋。
但其实 \(h[i] = min(p[i] - p[left(i)],p[right(i)] - p[i])\) 答案就是 \(\sum {(a[i] - h[i])}\)

出栈问题

维护一个后缀最大值,然后贪心的看,后面有比他大的,就压进来,否则弹出去。

仙人之环

仙人掌,所以可以 dfs 判环。
那么首先断开非环边一定可以增加连通块,断完还有剩余的,就考虑按环从小到大贪心断了。

const int N = 4e6 + 5;
int n, m, k, kk, u, v, tot, ans, num, d[N], st[N];
vector<int> g[N];
void dfs(int u, int fa) {
    d[u] = d[fa] + 1;
    for (int v : g[u]) {
        if (v == fa)
            continue;
        if (!d[v])
            dfs(v, u);
        else if (d[v] < d[u]) {
            if (d[u] - d[v] > 1)
                st[++tot] = d[u] - d[v] + 1, num += d[u] - d[v] + 1;
        }
    }
}
signed main() {
    // freopen("c.in","r",stdin);freopen("c.out","w",stdout);
    read(n, m, k);
    rep(i, 1, m) {
        read(u, v);
        g[u].push_back(v);
        g[v].push_back(u);
    }
    rep(i, 1, n) if (!d[i])++ ans, dfs(i, 0);
    if (k <= m - num)
        return printf("%d", k + ans), 0;
    sort(st + 1, st + 1 + tot);
    k -= m - num, ans += m - num;
    rrep(i, tot, 1) {
        if (k >= st[i])
            k -= st[i], ans += st[i] - 1;
        else {
            ans += k - 1;
            printf("%d\n", ans);
            break;
        }
    }
}
posted @ 2022-08-25 13:10  Xu_brezza  阅读(44)  评论(0编辑  收藏  举报