「ABC305H-Shojin」题解
Ex - Shojin
sol
首先我们可以不考虑 \(a=1\) 的问题,它们不管怎么分,肯定是放在最后最优。因此最后统计答案把它们的 \(b\) 一并加上即可。
考虑剩下的序列,\(a\) 至少为 \(2\),那么一个区间的长度不会超过 \(\log x+1\)。也就是说,不考虑限制的情况下,暴力 DP 复杂度是 \(O(n\log n)\) 的。
考虑限制,这个就很典了,WQS 二分一下即可,凸性显然。
记得特判 \(a\) 全为 \(1\) 的情况,至少得有一个区间。
至于为什么 \(l\) 不会为 \(0\) 导致错误,因为区间的贡献至少为 \(1\),因此 \(l=1\) 时与 \(l=0\) 时等价,都是一个点一个区间。所以最后 \(l\) 至少为 \(1\)。
code
const int N=2e5+5,T=30;
int n,t;
ll x,b;
struct node{ll a,b;}ns[N],a[N];
inline bool operator<(const node &x,const node &y){return x.b*(y.a-1)<y.b*(x.a-1);}
int idx;
ll calc[N][T],sum[N];
multiset<node> st;
inline void init(){
int m=0;
rep(i,1,n){
if(ns[i].a>1)a[++m]=ns[i];
else b+=ns[i].b;
}
n=m;
rep(l,1,n){
st.clear();
rep(j,0,t){
if(l+j>n)break;
st.insert(a[l+j]);
for(auto i:st)calc[l][j]*=i.a,calc[l][j]+=i.b,chmin(calc[l][j],x+1);
}
}
}
pli f[N];
pli check(ll dlt){
rep(i,1,n)f[i]={INF,INF};
rep(i,1,n)rep(j,0,t){
if(!(i-j))break;
if(calc[i-j][j]>x)break;
chmin(f[i],pli({f[i-j-1].fir+calc[i-j][j]+dlt,f[i-j-1].sec-1}));
}
return {f[n].fir+f[n].sec*dlt+b,-f[n].sec};
}
inline void Main(){
read(n,x);t=__lg(x);
rep(i,1,n)read(ns[i].a,ns[i].b);
init();
ll l=0,r=x;
while(l<r){
ll m=l+r+1>>1;
if(check(m).fir<=x)l=m;
else r=m-1;
}
auto ans=check(l);
int k=ans.sec-(x-ans.fir)/l;
put(k?k:1,' '),put(ans.fir+l*(ans.sec-k));
}

浙公网安备 33010602011771号