NC24083 [USACO 2017 Dec P]Greedy Gift Takers

2022/6/28 23:26:00

本文主要是介绍NC24083 [USACO 2017 Dec P]Greedy Gift Takers,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

NC24083 [USACO 2017 Dec P]Greedy Gift Takers

题目

题目描述

Farmer John's nemesis, Farmer Nhoj, has N cows (\(1≤N≤10^5\)), conveniently numbered 1…N. They have unexpectedly turned up at Farmer John's farm, so the unfailingly polite Farmer John is attempting to give them gifts.

To this end, Farmer John has brought out his infinite supply of gifts, and Nhoj's cows have queued up in front of him, with cow 1 at the head of the queue and cow N at the tail. Farmer John was expecting that at every timestep, the cow at the head of the queue would take a gift from Farmer John and go to the tail of the queue. However, he has just realized that Nhoj's cows are not that polite! After receiving her gift, each cow may not go to the tail of the queue, but rather may cut some number of cows at the tail, and insert herself in front of them. Specifically, cow ii will always cut exactly cic_ici cows (\(0≤c_i≤N−1\)).

Farmer John knows that some cows might receive multiple gifts; as he has an infinite supply, this does not worry him. But he is worried that some cows might become unhappy if they do not get any gifts.

Help Farmer John find the number of cows who never receive any gifts, no matter how many gifts are handed out.

输入描述

The first line contains a single integer, N.
The second line contains N space-separated integers \(c_1,c_2,…,c_N\) .

输出描述

Please output the number of cows who cannot receive any gifts.

示例1

输入

3
1 2 0

输出

1

题解

思路

知识点:二分。

第一个难点是要注意到,可行性函数是关于队伍的第几头牛的,因为发现如果某头牛拿不到礼物那他之后的牛一定拿不到,而拿的到的牛之前的牛一定拿得到,因此答案位置处于函数零点,且函数单调。

第二个难点是如何写可行性检验的函数。我们先统计 \(mid\) 牛之前的牛的 \(cnt[i]\) ,表示牛插到第 \(i(1\leq i < mid)\) 个位置的数量,而且 \(cnt[i]\) 只会随 \(mid\) 靠前减少,而不会更改或者变多,因为牛要么排到后面要么还在 \(1\leq i <mid\) 。对于第 \(i\) 个位置,若 \(\sum_{i=1}^i cnt[i] \geq i\) ,说明 \(mid\) 牛之前肯定会存在 \(\geq i\) 的牛插队到 \(\leq i\) 的位置,由于,所以队伍始终至少在 \(i\) 之前循环,所以不可能到达 \(mid\) 牛;而 \(\sum_{i=1}^i cnt[i] < i\) 说明,在 \(mid\) 牛之前会存在 \(< i\) 的牛插队到 \(\leq i\) 的位置,即 \(\leq i\) 的队伍一定长度缩短,而且这些牛之后会到同样位置,因此 \(cnt[i]\) 不增,即 \(\leq i\) 排队的牛会不增,表示 \(\leq i\) 的队伍必定不会循环,特别地如果 \(\sum_{i=1}^{mid-1} cnt[i] < mid-1\) ,即表示 \(\leq mid-1\) 的队伍必定不会循环,即可行。

时间复杂度 \(O(n \log n)\)

空间复杂度 \(O(n)\)

代码

#include <bits/stdc++.h>

using namespace std;

int n;
int c[100007], cnt[100007];

bool check(int mid) {///判断是否拿得到
    memset(cnt, 0, sizeof(cnt));
    int sum = 0;
    for (int i = 1;i < mid;i++) cnt[c[i]]++;
    for (int i = 1;i < mid;i++) {
        sum += cnt[i];
        if (sum >= i) return 0;
    }
    return 1;
}

int main() {
    std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);

    cin >> n;
    for (int i = 1;i <= n;i++) cin >> c[i], c[i] = n - c[i];

    int l = 1, r = n;
    while (l <= r) {
        int mid = l + r >> 1;
        if (check(mid)) l = mid + 1;
        else r = mid - 1;
    }
    cout << n - r << '\n';///n减最后一个拿得到的位置(第一个拿不到的位置减一) = 拿不到的总数
    return 0;
}


这篇关于NC24083 [USACO 2017 Dec P]Greedy Gift Takers的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程