题目大意:有n个植物排成一排,标号为1-n,每株植物有自己的生长速度ai,每对植物浇一次水,该株植物就长高ai,现在机器人从第0个格子出发,每次走一步,不能停留,每一步浇一次水,总共可以走m步,问最矮的植物最高是多少。
思路:
一般此类最小值最大问题都是二分,此题显然也是可以二分植物的高度的。
确定某一个高度后,也确定了每个植物需要浇几次水,而对于一株植物来说,应当尽可能的在这株植物和后面那个格子来回走,是这株植物迅速超过最低高度(这样的走法是最优的,因为可以想象,如果往后走很多步再走回来,中间浪费的可能性比较大),于是就是对n个植物模拟浇水,考虑一些细节就可以了(二分跳出条件,long long等等)
//#pragma comment(linker,"/STACK:102400000,102400000") #include<cstdio> #include<algorithm> #include<iostream> #include<vector> #include<map> #include<set> #include<cstring> #include<cmath> #include<queue> #include<stack> #include<stdlib.h> //#include<unordered_map> #define lson l,mid,rt<<1 #define rson mid+1,r,(rt<<1)|1 #define CLR(a,b) memset(a,b,sizeof(a)) #define mkp(a,b) make_pair(a,b) typedef long long ll; using namespace std; inline ll read(){ ll x=0,f=1; char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f;} const int maxn=100010; int n; ll a[maxn],c[maxn],m; inline bool judge(ll high){ CLR(c,0); ll temp=m; if(m==0)return false; c[1]=a[1],m--; int i=1; for(;i<=n;i++) { if(m<=0)break; if(c[i]>=high) { if(m>0) { c[i+1]=a[i+1]; m--; continue; }else{ break; } } ll tmp=(ll)ceil((high-c[i])*1.0/a[i]); if(m>2*tmp){ m-=2*tmp+1; c[i]+=a[i]*tmp; c[i+1]+=a[i+1]*(tmp+1); continue; }else if(m==2*tmp){ c[i]+=a[i]*tmp; c[i+1]+=a[i+1]*tmp; break; }else{ break; } } m=temp; for(i=1;i<=n;i++) { if(c[i]<high)return false; } return true; } int main(){ int t; cin>>t; while(t--) { cin>>n>>m; ll l=0,r=0,mid,ans; for(int i=1;i<=n;i++){ a[i]=read(); r=max(r,a[i]*m); } if(m==0){ printf("0\n"); continue; } while(l<=r) { mid=(l+r)>>1; // printf("mid %d\n",mid); if(judge(mid)) { ans=mid; l=mid+1; }else{ r=mid-1; } } printf("%lld\n",ans); } }