Height Profile(线段树)

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*/

发布了750 篇原创文章 · 获赞 320 · 访问量 18万+

猜你喜欢

转载自blog.csdn.net/jk_chen_acmer/article/details/104727302
今日推荐