2118: 签到题
时间限制: 1 Sec 内存限制: 128 MB
提交: 54 解决: 22
[提交] [状态] [讨论版] [命题人:admin]
题目描述
作为acm集训队一员的你,有一天拿到了你的历史训练时长记录表。你当然是想让你的训练时长看起来好看一些,所以你想调整这份记录表,使得训练时长最少的一天的时间在所有可能的调整方案中最大。你还有m分钟就梦醒了,时间紧迫,你每一分钟可以使得连续的w天时长记录多一个单位时间。注意,在梦中,你不需要考虑一天有多少的时间限制。 输出经过你的调整,最小的时长。(睡醒前的答案)
输入
多组数据,第一行为一个整数T,表示数据组数(T<=10) 接下来每组数据,开头为n,m,w(1<=w , n<=100000, 0<=m <= 1000000),表示有记录的历史训练天数 接下来一行n个数,表示这一天你的签到时长t(0<=t<=1000000)
输出
输出T行,每行代表一组的答案。
样例输入
1
3 2 1
2 1 2
样例输出
2
二分答案,差分检查。
#include<bits/stdc++.h>
#define fi first
#define se second
#define log2(a) log(n)/log(2)
#define show(a) cout<<a<<endl;
#define show2(a,b) cout<<a<<" "<<b<<endl;
#define show3(a,b,c) cout<<a<<" "<<b<<" "<<c<<endl;
#define tim printf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC);
using namespace std;
typedef long long ll;
typedef pair<ll, ll> P;
typedef pair<P, ll> LP;
const ll inf = 0x3f3f3f3f;
const int N = 2e5+10;
const ll mod = 1e12;
const ll p=1e6;
const int base=131;
const double pi=acos(-1);
int a[N],n,rm,w,m;
int num[N];
bool check(int x)
{
for(int i=1;i<=n;i++) num[i]=0;
int t;
m=rm;
for(int i=1;i<=n;i++)
{
num[i]+=num[i-1];
if(num[i]+a[i]<x)
{
t=x-a[i]-num[i];
m-=t;
num[i]+=t;
num[i+w]-=t;
}
}
return m>=0 ? 1 : 0;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&rm,&w);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
int l=0,r=2000001,ans;
while(l<=r)
{
int mid=l+r>>1;
if(check(mid))
{
ans=mid;
l=mid+1;
}
else r=mid-1;
}
printf("%d\n",ans);
}
}