JZOJ 4017 逃跑

Description

Konrad, Delfador 和 Kalenz 一行人又喜闻乐见地被追杀了。
他们面临的是一条有 N 个地点的路, 他们从 0 号地点出发, 要逃到 N 号地点去。每个地点的战斗都有一定的金币收入 Ai,也有一定的部队损失 Bi。
为了更好地逃生, Delfador 还弄到了一块传送宝石,这样一行人就能向后传送不超过 L 的距离。从一个地点传送到另一个地点时,Konrad 会选择路径上除起点外的地形指数 Ci 最大的地点进行战斗,地形指数相同时选择最靠后的。
作为优秀的领导者, Konrad 希望总金币收入与总部队损失的比值最大。

Input

第一行,两个整数 N, L。
接下来 N 行,每行两个整数,分别表示 Ai, Bi, Ci。

Output

一行,一个实数,表示答案。
答案请使用科学计数法输出,保留 9 位小数,具体参见输出样例。指数为 0 时,最后应当输出'0.000000000e+000'。

Data Constraint

SOL

先吐槽一波,cout <<setprecision(9)<<scientific<<ans<<endl ; 

这玩意在windows 和 linux 下的结果是不一样的。

(⊙o⊙)…

发现求一个比值,这种题套路都是二分答案。

设当前二分值是p

记 Px=A-B*p, 视作选取一个点的代价。那么 DP方程: F[x]=max(f[j] + D[j -> i的战斗点])

那么anw>=p 的充要条件是 f[n+1]>=0

我们考虑单调队列维护一段区间的战斗点。然后用线段树维护 F+D[j->i 的战斗点]。

注意常数。

代码

#pragma GCC optimize("-Ofast")
#include<bits/stdc++.h>
#define exp 2e-11
#define Mid (l+r>>1)
#define ls no<<1,l,Mid
#define rs no<<1|1,Mid+1,r
#define db double
#define N 250007
using namespace std;
db ma[N],lazy[N];
void pange(int no,int l,int r,int x,db t){
    if (l==r) {
      ma[no]=t; return;    
    }
//    pushdown(no);
    lazy[no]=0;
    if (x<=Mid) pange(ls,x,t); else pange(rs,x,t);
    ma[no]=max(ma[no<<1],ma[no<<1|1]);
}
inline void pushdown(int no) {
    lazy[no<<1]+=lazy[no]; lazy[no<<1|1]+=lazy[no];
    ma[no<<1]+=lazy[no]; ma[no<<1|1]+=lazy[no];
    lazy[no]=0;
}
int L;int R;db ooz;
void change(int no,int l,int r) {
    if (L<=l&&r<=R) {
        ma[no]+=ooz; lazy[no]+=ooz;
        return;
    }
    pushdown(no);
    if (L<=Mid) change(ls);
    if (R> Mid) change(rs);
    ma[no]=max(ma[no<<1],ma[no<<1|1]);
}
db anx;
void que(int no,int l,int r,int L,int R) {
    if (L<=l&&r<=R) {
        anx=max(anx,ma[no]); return;
    }
    pushdown(no);
    if (L<=Mid) que(ls,L,R);
    if (R> Mid) que(rs,L,R);
}
int be,ed;
db f[N],d[N];
int q[N],a[N],b[N],n,c[N],l;
void clear(int no,int l,int r){
    ma[no]=0; lazy[no]=0;
    if (l==r) return;
    clear(ls); clear(rs);
}
bool check(db t) {
    clear(1,0,n);
    be=1,ed=1;
    f[1]=d[1]=a[1]-t*b[1];
    pange(1,0,n,1,f[1]);
    L=R=0; ooz=f[1]; change(1,0,n);
    q[ed++]=1;
    for (int i=2;i<=n;i++) {
       d[i]=a[i]-t*b[i];
       while (be<ed&&c[i]>=c[q[ed-1]]) {
           ed--;  
           L=q[ed-1]; R=q[ed]-1; ooz=-d[q[ed]];
            change(1,0,n);
       }
       L=q[ed-1]; R=i-1; ooz=d[i];
       change(1,0,n); q[ed++]=i; 
       anx=-1e9;
       que(1,0,n,max(i-l,0),i-1); f[i]=anx;
       pange(1,0,n,i,f[i]);
    }
//    f[n+1]=que(1,1,)
    return f[n]>-exp;
}
signed main () {
//    freopen("escape11.in","r",stdin);
//    freopen("")
    scanf("%d%d",&n,&l);
    for (int i=1;i<=n;i++)
     scanf("%d%d%d",&a[i],&b[i],&c[i]);
    n++; c[n]=-1;
    db t=1000000,ans=0;
    while (t>exp) {
        if (check(ans+t)) 
         ans+=t;
        t*=0.5;
    }
    int to=0;
    while (ans>10||ans<1) {
        if (ans>10) ans/=10,to++;
        if (ans<1) ans*=10,to--;    
    } 
//    cout<<ans<<endl;
    printf("%.9lfe",ans);
    if (to<0) putchar('-');else putchar('+')
    ;printf("00%d",abs(to));
//    cout <<setprecision(9)<<scientific<<ans<<endl ; 
}

 

 

 
posted @ 2018-07-13 15:04  泪寒之雪  阅读(284)  评论(0编辑  收藏  举报