您的位置:首页 > 运维架构

hdu 3717 二分+队列维护

2013-10-17 15:31 447 查看
思路:已知当前的总长度和为len,当前的伤害为sum,伤害次数为 num.那么对下一个点的伤害值sum=sum+2*len+num;

这个是通过(x+1)^2展开化简就能得到。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
#define Maxn 100010
#define LL __int64
#define inf  1e12
using namespace std;
LL num[Maxn],cnt[Maxn],n,k;
bool OK(LL x)
{
LL suma,sumb,ans,po,i,numa;
LL j=n;
suma=sumb=ans=numa=0;
for(i=n;i>=1;i--){
if(j>i){
while((j-i)*(j-i)>=x){
suma-=cnt[j]*(j-i-1)*(j-i-1);
sumb-=cnt[j]*(j-i-1);
numa-=cnt[j];
j--;
}
}
suma+=2*sumb+numa;
sumb+=numa;
if(num[i]-numa*x+suma<0) cnt[i]=0;
else cnt[i]=(num[i]-numa*x+suma)/x+1;
numa+=cnt[i];
ans+=cnt[i];
}
return ans<=k;
}
int main()
{
int i,j,t;
LL mx;
scanf("%d",&t);
while(t--){
scanf("%I64d%I64d",&n,&k);
mx=0;
for(i=1;i<=n;i++){
scanf("%d",&num[i]);
mx=max(mx,num[i]);
}
LL l,r,mid;
l=1,r=inf;
while(l<r){
mid=(l+r)>>1;
if(OK(mid))
r=mid;
else
l=mid+1;
}
printf("%I64d\n",l);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: