DP 都是正常去做,样例也很对,然后就错了。
这个是代码
#include<bits/stdc++.h>
using namespace std;
#define ld double
const ld eps=1e-15,inf=1e15+7;
const int N=2e5+7;
ld f[N],tmp[N];int g[N],tr[N<<2],sign[N<<2],n,m,tot=0;
struct node{ld k,b;}seg[N];
ld get(int id,int x){return seg[id].k*tmp[x]+seg[id].b;}
bool eq(ld x,ld y){ld z=x-y;return (z<=eps&&z>=-eps);}
bool cmp(int u,int v,int x){ld a=get(u,x),b=get(v,x);return (a>b)||(eq(a,b)&&g[u]<g[v]);}//尽量使分的段数最小
#define ls (u<<1)
#define rs (u<<1|1)
#define mid ((l+r)>>1)
void update(int u,int l,int r,int x){
if(sign[u]!=tot)sign[u]=tot,tr[u]=n+1;
if(cmp(x,tr[u],tmp[mid]))swap(tr[u],x);
if(cmp(x,tr[u],tmp[l]))update(ls,l,mid,x);
if(cmp(x,tr[u],tmp[r]))update(rs,mid+1,r,x);
}
int query(int u,int l,int r,int x){
if(sign[u]!=tot)sign[u]=tot,tr[u]=n+1;
if(l==r)return tr[u];
int res=x<=mid?query(ls,l,mid,x):query(rs,mid+1,r,x);
return cmp(tr[u],res,x)?tr[u]:res;
}
void calc(ld val){//记得加初始化
seg[n+1]={0,-inf};f[n]=0;seg[n]={(-1.0)/n,1.0};update(1,0,n,n);
for(int i=n-1;i>=0;i--){
int j=query(1,0,n,i);
f[i]=get(j,i)+val,g[i]=g[j]+1;
if(i==0)break;
seg[i]={(-1.0)/i,1.0+f[i]};update(1,0,n,i);
}
}
#undef mid
signed main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>n>>m;for(int i=1;i<=n;i++)tmp[i]=i;
ld l=-1e10,r=1e10,mid,ans=-1e10;
while(!eq(l,r)){
mid=(l+r)/2.0;tot++;calc(mid);
if(g[0]>=m) ans=mid,r=mid;else l=mid;
}
calc(ans);cout<<fixed<<setprecision(9)<<(f[0]-1.0*g[0]*ans);return 0;
}
求救救。