题目:CodeForces - 279 B. Books
题意 :
给定一个时间
t
t
t
给定一个书的总数量
n
n
n
给了读完一本书需要话的时间的数组
形如:
然后我们找到一个连续的区间,区间要求读完这个区间的书的总时间小于等于给定的时间
t
t
t
并且要求这个区间的书的数量最大,也就是区间的长度最大
例:选择1 2 1三本书,花时间4,读了3本书,比其他的情况读的书多,并且是合法的
输入:
4 5
3 1 2 1
输出:
3
思路:
枚举每一本书
- 如果加上这本书后,总和小于等于t,那么就加入队列q中,然后更新最大值和总和。
- 如果加上这本书后,总和大于t,那么仍然将这本书加入队列,更新总和,并从队头开始弹出元素,直到总和小于等于t。
所以每本书都是要插入队列的。如果插入后总和大于t,就开始弹出队头元素。最后更新最大值时,如果需要弹出队头,就与当前元素个数-1比较,否则与当前元素个数比较。
#include <iostream>
#include <queue>
#define int long long
using namespace std;
const int N = 100010;
int a[N];
int n, t;
queue<int> q;
signed main()
{
cin >> n >> t;
for(int i = 1 ; i <= n ; i ++) cin >> a[i];
int maxv = 0; // 记录最大值
int sum = 0; // 记录当前队列的和
int con = 0; // 记录当前队列的长度
for(int i = 1 ; i <= n ; i ++)
{
if(a[i] > t) continue; // 如果这本书的值完全大于这个时间
maxv = max(maxv, a[i]); // 时间是合法的直接更新时间
if(sum + a[i] <= t)
{
// 如果是合法的
q.push(a[i]);
con = max(con, (int)q.size());
sum += a[i];
}
else
{
// 不合法的话, 就要开始弹出队头元素了
while(sum + a[i] > t)
{
sum -= q.front();
q.pop();
}
q.push(a[i]);
sum += a[i];
}
}
cout << con << endl;
return 0;
}