舞蹈演出 Problem ID: 8516 Time Limit Exceeded 90 分 求救!!!

题目描述:

约翰家的 N 头奶牛要参加跳舞演出。舞台能支持 K 头奶牛同时跳舞,每头奶牛都有一个跳舞的时长 di。初始时编号为 1~K 的奶牛同时登台跳舞,每当一头奶牛结束它的舞蹈,下一头奶牛就会立刻登台跳舞。现要求演出总时间不超过 T,求 K 的最小值。

输入格式:

第一行输入两个正整数 N 和 T。

第二行输入 N 个正整数,第 i 个正整数为 di。

输出格式:

一行一个正整数,表示 K 的最小值。

样例输入1:

5 8
4 7 8 6 4

样例输出1:

4

样例输入2:

5 8
2 3 3 3 3

样例输出2:

2

样例输入3:

7 100
1 23 88 3 2 77 25

样例输出3:

3

数据规模:

1≤N≤10000,1≤T≤1000000,1≤di≤100000。

保证 K=N 时表演会按时完成。

AC代码如下:

#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<queue>
#include<iostream>
#include<algorithm>
#pragma GCC optimize(2)
#pragma G++ optimize(2)
using namespace std;
int n,t,a[100005];
priority_queue<int,vector<int>,greater<int> >q;
bool ch(int i)
{
    int j=1,bowl=0;
    for(j;j<=i;j++)
    q.push(a[j]);
    while(j<=n&&bowl<=t){
    bowl+=(q.top()-bowl);
    q.pop();q.push(a[j++]+bowl);
    }while(!q.empty()){
    bowl+=(q.top()-bowl);
    q.pop();}return bowl<=t;
}
int main()
{
    ios_base::sync_with_stdio(false);
	cin.tie(NULL);cin>>n>>t;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    int l=1,r=n,m;
    while(l<r)
    {
        m=(l+r)/2;if(ch(m))
        r=m;else l=m+1;
    }cout<<r;return 0;
}
1 个赞

这题正解是二分吧。

3 个赞

由于答案具有单调性,如果 x 满足条件,那么 x+1 及以上一定不是最小的,否则 x 及以下一定是不符合要求的,然后对于每个中间数 mid ,使用优先队列计算出最后跳完的时间判断是否合法即可。

5 个赞

唔,我试试

1 个赞

换句话说,你那个枚举 i 换成二分就应该对了

2 个赞

how 单调队列

我只会线段树/kk

2 个赞

《排序》

2 个赞

说错了,是优先队列

2 个赞

应该是优先队列/kk

2 个赞

二分AC了

1 个赞

。。。。。。。。

1 个赞

二分复杂度是 O(n \log^2 n) 的,你枚举最坏是 O(n^2 \log n) 的,显然 T 吧。

3 个赞

emmmmmm。。。。。。

1 个赞

yydz,鉴定为线段树学魔怔了(metoo

1 个赞

其实线段树是真的很常用的。

1 个赞

是这样的

1 个赞

但是我感觉 lzy 是写主席树写魔怔了 :rofl:

1 个赞

啊?有吗

1 个赞

see QQ

1 个赞

az,但是主席树不是可持久化线段树吗(

不也是线段树啊

1 个赞