题目描述
在ACM队暑假集训的某一天,实验室里有 n个人。因为天气很热,大家都很想吃西瓜。
于是Eric买了 m个西瓜拿到了实验室。Eric把这 n个人分别编号为 1,2,3...n,他希望这 n个人循环轮流来吃西瓜。
也就是说从 1号开始,然后 2号, 3号... n号依次吃西瓜, n号吃完后又轮到 1号来吃,直到这 m个西瓜被吃完。
而这 n个人每个人有一个肚量值,第i个人的肚量值为 ai。
lililalala是这 n个人肚量值最大的人,不仅如此,他还非常贪吃,每次轮到他吃西瓜时,都会直接吃掉等同于他的度量值数量的西瓜。如果剩余的西瓜已经不够吃了,那么他会把所有西瓜直接吃完。(是的他很能吃)除了lililalala以外的其他人,对于第 i号每次吃西瓜可以选择吃掉 [1,ai]中任意整数数量个西瓜。当然,不能超过当前剩余的西瓜数量。
为了使吃西瓜更有意思一些,Eric规定如果在轮到某个人吃西瓜时没有西瓜了,那么由他来打扫一次实验室。(是的大家都很能吃)
其他人都觉得lililalala吃的太多了应该由他来打扫卫生。请问在其他人串通好的情况下能否合理安排每个人的行动使得吃完西瓜后由lililalala来打扫卫生?
输入描述:
第一行一个数字T(1≤T≤50)--样例个数。
每个样例包含两行。
第一行两个数字n,m(1≤n≤105,0≤m≤106)。
第二行 n个数字a1,a2...an(1≤ai≤107),以空格分隔。
保证所有样例中肚量最大的人只有一个。这个人是lililalala。
保证所有样例中 ∑n不超过 3×106。
保证所有样例中 ∑m不超过 107。
输出描述:
每个样例输出一行,输出”YES”如果合理安排可以使得最后由lililalala来打扫卫生,否则输出“NO”。
输入
2
4 3
1 2 3 2
5 8
1 2 3 2 1
输出
YES
NO
说明
第一个样例中lililalala是3号:
一种可行的方案:
1号吃掉1个西瓜
2号吃掉2个西瓜
第一次到3号吃西瓜时就没有西瓜可以吃了,所以3号需要打扫卫生。
第二个样例无论怎样安排各个人在每一次吃西瓜的数量,也不能达成目标。
分析
可以循环维护到每个人吃西瓜时的西瓜数量的区间[L,R],复杂度是O(m)。初始L=m,R=m,对于非最大肚量的人,L每次减1(至少吃一个),R每次减a[i],至多吃a[i]个。对于最大肚量的人,L和R都减a[i]。如果某个非最大肚量的人吃西瓜的时候L>0,那么答案为NO,如果最大肚量的人吃西瓜的时候R<0,那么答案为YES。
代码
#include<iostream>
#include<cstdio>
#include<string.h>
#include<algorithm>
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<stdlib.h>
using namespace std;
typedef long long ll;
const int N=3000005;
int a[N];
int main()
{
int t,n,m,id;
scanf("%d",&t);
while(t--)
{
int maxi=-1;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(a[i]>maxi)
{
maxi=a[i];
id=i;
}
}
int l=m,r=m;//初始化
int flag=1;
while(flag)
{
for(int i=1;i<=n;i++)
{
if(i==id)
{
l-=a[i];
r-=a[i];
if(r<0)
{
printf("YES\n");
flag=0;
break;
}
}
else
{
l-=1;
r-=a[i];
if(l<0)
{
printf("NO\n");
flag=0;
break;
}
}
}
}
}
return 0;
}