JZOJ 4017 逃跑
Description
Konrad, Delfador 和 Kalenz 一行人又喜闻乐见地被追杀了。
他们面临的是一条有 N 个地点的路, 他们从 0 号地点出发, 要逃到 N 号地点去。每个地点的战斗都有一定的金币收入 Ai,也有一定的部队损失 Bi。
为了更好地逃生, Delfador 还弄到了一块传送宝石,这样一行人就能向后传送不超过 L 的距离。从一个地点传送到另一个地点时,Konrad 会选择路径上除起点外的地形指数 Ci 最大的地点进行战斗,地形指数相同时选择最靠后的。
作为优秀的领导者, Konrad 希望总金币收入与总部队损失的比值最大。
他们面临的是一条有 N 个地点的路, 他们从 0 号地点出发, 要逃到 N 号地点去。每个地点的战斗都有一定的金币收入 Ai,也有一定的部队损失 Bi。
为了更好地逃生, Delfador 还弄到了一块传送宝石,这样一行人就能向后传送不超过 L 的距离。从一个地点传送到另一个地点时,Konrad 会选择路径上除起点外的地形指数 Ci 最大的地点进行战斗,地形指数相同时选择最靠后的。
作为优秀的领导者, Konrad 希望总金币收入与总部队损失的比值最大。
Input
第一行,两个整数 N, L。
接下来 N 行,每行两个整数,分别表示 Ai, Bi, Ci。
接下来 N 行,每行两个整数,分别表示 Ai, Bi, Ci。
Output
一行,一个实数,表示答案。
答案请使用科学计数法输出,保留 9 位小数,具体参见输出样例。指数为 0 时,最后应当输出'0.000000000e+000'。
答案请使用科学计数法输出,保留 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 ; }