\(\tt\bf{I. AT\_abc370\_f}\)
首先套路的破換成鏈,然後二分答案 \(p\)。
對於每一個二分的答案 \(p\),考慮先二分出 \(f_{i,0}\) 表示 \(i\) 之後第一個滿足 \(\sum\limits_{j=i}^{f_{i,0}} a_j\ge p\) 的 \(f_{i,0}\),然後倍增的設 \(f_{i,j}\) 表示 \(i\) 之後滿足 \(2^j\) 次上述條件的下標為 \(f_{i,j}\)。特殊的若不可以滿足則令 \(f_{i,j}=-1\)。
然後考慮列舉起點,直接暴力倍增計算出 \(k\) 次操作之後的答案即可。時間複雜度為 \(O(n\log^2n)\)。程式碼有點混亂。
const int N=400100,mod=998244353;
int a[N],s[N],n,k,now,nxt[N][20],res;
bool chk(int p){
memset(nxt,-1,sizeof nxt);
F(i,1,n+n){
int l=i,r=i+n-1,best=-2;
r=min(r,n+n);
while(l<=r){
int mid=l+r>>1;
if(s[mid]-s[i-1]>=p)best=mid,r=mid-1;
else l=mid+1;
}
nxt[i][0]=best+1;
}
nxt[n+n+1][0]=n+n+1;
F(i,1,19)
F(j,1,n+n+1)
if(~nxt[j][i-1])
nxt[j][i]=nxt[nxt[j][i-1]][i-1];
// F(i,1,n+n)
// cout<<i<<": "<<nxt[i][0]<<' '<<nxt[i][1]<<" qwq\n";
int cnt=0;
F(i,1,n){
int x=i;
G(j,19,0)
if(k>>j&1){
x=nxt[x][j];
if(x==-1||x>i+n)break;
}
if(x!=-1&&x<=i+n)
++cnt;
}
if(cnt)
res=n-cnt;
return !!cnt;
}
signed main(){
cin>>n>>k;
F(i,1,n)cin>>a[i],s[i]=s[i-1]+a[i];
F(i,1,n)a[i+n]=a[i],s[i+n]=s[i+n-1]+a[i];
int l=1,r=s[n],best=-1;
while(l<=r){
int mid=l+r>>1;
if(chk(mid))best=mid,l=mid+1;
else r=mid-1;
}
cout<<best<<' '<<res<<'\n';
}