不知道为什么,最近总是在摆,好不容易 vp 一场也是随便糊弄。。。
只能说,。
「无论憧憬真挚与否 怜悯的缘由存在与否
沉谜底于心 笃信这缕光会为我指引」
054 CF1329E Dreamoon Loves AA
我们考虑一对 \((l,r)\) 需要满足的条件:
- \(\forall 1\leqslant i\leqslant m,\lceil\frac nr\rceil\leqslant \lfloor\frac nl\rfloor\)。
- \(\sum_{i=1}^m\lceil\frac nr\rceil\leqslant m+k\leqslant \sum_{i=1}^m\lfloor\frac nl\rfloor\)。
限制二可以拆开考虑,先二分出满足前面小于等于的最小 \(r\)(记作 \(r_0\)),以及满足后面小于等于的最大 \(l\)(记作 \(l_0\))。
若 \(l_0\geqslant r_0\),我们任选一对 \(l=r\),有 \(\sum_{i=1}^m\lceil\frac nr\rceil= \sum_{i=1}^m\lfloor\frac nl\rfloor\),可得 \(\lceil\frac nr\rceil= \lfloor\frac nl\rfloor\),满足条件。
否则,我们考虑调整 \(l_0,r_0\) 的取值使得满足限制一。
由于 \(l<r\),所以 $ \lfloor\frac nl\rfloor-\lceil\frac nr\rceil\geqslant -1$,我们需要将其调整到 \(0\),容易发现其会产生一个限制“\(l\leqslant L_k\) 或 \(r\geqslant R_k\)”。
枚举左端点取值直接做就好了,复杂度 \(O(m\log m)\)。
#include<stdio.h>
#include<algorithm>
#define int long long
#define inf 2000000000000000
using namespace std;
const int maxn=400005;
int T,n,k,m,l0,r0,ls,ans;
int p[maxn],q[maxn];
struct limit{
int l,r;
}l[maxn];
inline int cmp(limit a,limit b){
return a.l<b.l;
}
signed main(){
scanf("%lld",&T);
while(T--){
scanf("%lld%lld%lld",&n,&m,&k),ls=0,ans=inf;
for(int i=1;i<=m;i++)
scanf("%lld",&p[i]);
p[++m]=n;
for(int i=1;i<=m;i++)
q[i]=p[i]-p[i-1];
int L=0,R=n+1;
while(L+1<R){
int mid=(L+R)>>1,sum=0;
for(int i=1;i<=m;i++)
sum+=q[i]/mid;
if(sum>=m+k)
L=mid;
else R=mid;
}
l0=L;
L=0,R=n+1;
while(L+1<R){
int mid=(L+R)>>1,sum=0;
for(int i=1;i<=m;i++)
sum+=(q[i]+mid-1)/mid;
if(sum<=m+k)
R=mid;
else L=mid;
}
r0=R;
if(l0>=r0){
puts("0");
continue;
}
for(int i=1;i<=m;i++){
int L=(q[i]+r0-1)/r0,R=q[i]/l0;
if(L>R)
l[++ls]=limit{q[i]/L,R==0? inf:(q[i]+R-1)/R};
}
l[0]=limit{-inf,r0},l[++ls]=limit{l0,inf},sort(l+1,l+1+ls,cmp);
int mx=-inf;
for(int i=0;i<ls;i++)
mx=max(mx,l[i].r),ans=min(ans,mx-l[i+1].l);
printf("%lld\n",ans);
}
return 0;
}