「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));
}
posted @ 2025-07-09 11:32  LastKismet  阅读(6)  评论(0)    收藏  举报