我还是尽量修改一下吧;大家先别看了;
https://ac.nowcoder.com/acm/contest/893?&headNav=www#question
这个只需登录一下就能够看到题目,所以我就不把题目展示给大家了;这个题首先我没做出来;然后看了一下题解,想了好长时间,才有点懂了;
下面是题解:
两点
写法简单一点是O(m),复杂一点是O(n),两种都可以过
O(m)的方法:循环维护到每个人吃西瓜时的西瓜数量的区间[L,R]
初始L=R=m
对于非肚量最大的人L每次减一(至少吃一个),R每次减去能a[i](至多吃a[i]个)
对于肚量最大的人L和R都减去a[i]
直到某个非肚量最大的人吃西瓜的时候如果L<0,得到答案为No
或者肚量最大的人吃西瓜时R<0,那么说明可以成功,得到答案为Yes
O(n)方法类似,求出肚量最大的人之前和之后的人的肚量之和即可优化。
这个我的理解是区间问题;先看一下代码吧;我直接从AC的代码中找到一个有意思的代码复制过来了;
/**
* ┏┓ ┏┓
* ┏┛┗━━━━━━━┛┗━━━┓
* ┃ ┃
* ┃ ━ ┃
* ┃ > < ┃
* ┃ ┃
* ┃... ⌒ ... ┃
* ┃ ┃
* ┗━┓ ┏━┛
* ┃ ┃ Code is far away from bug with the animal protecting
* ┃ ┃ 神兽保佑,代码无bug
* ┃ ┃
* ┃ ┃
* ┃ ┃
* ┃ ┃
* ┃ ┗━━━┓
* ┃ ┣┓
* ┃ ┏┛
* ┗┓┓┏━┳┓┏┛
* ┃┫┫ ┃┫┫
* ┗┻┛ ┗┻┛
*/
// warm heart, wagging tail,and a smile just for you!
//
// _ooOoo_
// o8888888o
// 88" . "88
// (| -_- |)
// O\ = /O
// ____/`---'\____
// .' \| |// `.
// / \||| : |||// \
// / _||||| -:- |||||- \
// | | \\ - /// | |
// | \_| ''\---/'' | |
// \ .-\__ `-` ___/-. /
// ___`. .' /--.--\ `. . __
// ."" '< `.___\_<|>_/___.' >'"".
// | | : `- \`.;`\ _ /`;.`/ - ` : | |
// \ \ `-. \_ __\ /__ _/ .-` / /
// ======`-.____`-.___\_____/___.-`____.-'======
// `=---='
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// 佛祖保佑 永无BUG
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********\n")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"
const int BufferSize = 1 << 16;
char buffer[BufferSize], *head, *tail;
inline char Getchar()
{
if(head == tail) {
int l = fread(buffer, 1, BufferSize, stdin);
tail = (head = buffer) + l;
}
return *head++;
}
inline int read()
{
int x = 0, f = 1; char c = Getchar();
for(; !isdigit(c); c = Getchar()) if(c == '-') f = -1;
for(; isdigit(c); c = Getchar()) x = x * 10 + c - '0';
return x * f;
}
const double eps = 1e-8;
const int mod = 1e9 + 7;
const int maxn = 3e5 + 5;
const int INF = 0x3f3f3f3f;
const LL INFLL = 0x3f3f3f3f3f3f3f3f;
int a[maxn];
int main()
{
#ifndef ONLINE_JUDGE
FIN
#endif
int T;
scanf("%d", &T);
while(T--)
{
int n, m;
scanf("%d%d", &n, &m);
LL sum = 0;
int maxx = -1;
int pos;
for(int i = 0; i < n; i++)
{
scanf("%d", &a[i]);
if(a[i] > maxx)
{
maxx = a[i];
pos = i;
}
sum += a[i];
}
LL l = m;
LL r = m;
int flag = 0;
for(int i = 0;; i++)
{
i %= n;
if(i == pos)
{
if(l <= 0)
{
flag = 1;
break;
}
l -= a[i];
r -= a[i];
}
else
{
if(r <= 0)
{
flag = 0;
break;
}
l -= a[i];
r--;
}
}
if(flag)
{
printf("YES\n");
}
else
{
printf("NO\n");
}
}
return 0;
}
这个代码中的l和r和题解中的l 和 r位置正好相反;
我是按照题解来解释的;
对于这个题,我们可以这样想,就是取最大值和最小值,最大是每个人吃ai个西瓜,最少是每个人吃1个西瓜,也就是每次每个人吃1个西瓜;当然肚量最大的那个人每次吃最多西瓜;
从这个代码中我们可以看出,让这个循环结束的条件有两个,1是当每个人吃一个西瓜的时候,还有没轮到肚量最大的那个人吃的时候结束了,证明不可以被套路;2 是当每个人吃·ai(也就是每个人可以吃的最大个)西瓜的时候,此时可以吃的西瓜为每次加上 ai;
只要到 最大肚量的那个人之前,r>0并且l<0;这样就可以套路他;
题解大体就是这个意思,我感觉自己说的不是很清楚;当然那个o(m)的方法,也是这个思路;