https://vjudge.net/problem/Gym-102500H
题意:
给出0~n点的海拔,求最长的线段,满足斜率大于等于k。可以是小数。
解析:
假设最后线段两头都不是端点(小数长度),那么这两条如果斜率一样,可以将一条减少,另外一条补满。如果不一样,一定有一条更优,那么这条多一些,另外一条少一些。最后还是一条布满了。
所以最后的结果一定是一头停在端点上。
假设现在斜率为k,那么两个点i,j满足要求,当且仅当a[i]-ik<=a[j]-jk。所以做一个线段树,求后面最后面的大于等于点i的点即可。
最后往两头伸展即可。
代码:
/*
* Author : Jk_Chen
* Date : 2020-03-07-12.48.25
*/
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i,a,b) for(int i=(int)(a);i<=(int)(b);i++)
#define per(i,a,b) for(int i=(int)(a);i>=(int)(b);i--)
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define pill pair<int, int>
#define fi first
#define se second
#define debug(x) cerr<<#x<<" = "<<x<<'\n'
const LL mod=1e9+7;
const int maxn=1e5+9;
const int inf=0x3f3f3f3f;
LL rd(){ LL ans=0; char last=' ',ch=getchar();
while(!(ch>='0' && ch<='9'))last=ch,ch=getchar();
while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
if(last=='-')ans=-ans; return ans;
}
#define rd rd()
/*_________________________________________________________begin*/
double a[maxn];
double val;
double getval(int pos){
return a[pos]-pos*val;
}
double tr[maxn<<2];
#define ls (rt<<1)
#define rs (rt<<1|1)
#define mid (l+r>>1)
#define root int rt,int l,int r
#define lson ls,l,mid
#define rson rs,mid+1,r
void build(root){
if(l==r){
tr[rt]=getval(l);
return;
}
build(lson);build(rson);
tr[rt]=max(tr[ls],tr[rs]);
}
int query(root,int L,int R,double v){
if(tr[rt]<v)return -1;
if(l>=L&&r<=R){
if(l==r){
return l;
}
if(tr[rs]>=v)
return query(rson,L,R,v);
return query(lson,L,R,v);
}
int ans=-1;
if(R>mid)
ans=query(rson,L,R,v);
if(ans==-1&&L<=mid)
ans=query(lson,L,R,v);
return ans;
}
int main(){
int n=rd,q=rd;
rep(i,0,n){
a[i]=rd;
}
while(q--){
scanf("%lf",&val);
val*=10;
double mx=-1;
build(1,0,n);
rep(i,0,n-1){
int pos=query(1,0,n,i+1,n,getval(i));
if(pos==-1)continue;
mx=max(mx,1.0*pos-i);
if(pos<n){
double add=(getval(pos)-getval(i))/(getval(pos)-getval(pos+1));
mx=max(mx,1.0*pos-i+add);
}
if(i>0){
if(getval(i-1)<=getval(i)||getval(i-1)<=getval(pos))continue;
double add=(getval(pos)-getval(i))/(getval(i-1)-getval(i));
mx=max(mx,1.0*pos-i+add);
}
}
if(mx<0)
puts("-1");else
printf("%.10f\n",mx);
}
return 0;
}
/*_________________________________________________________end*/