感谢联考集团
感觉挺有意思的一个题。
考虑一个直接贪心的做法。
首先发现连续三段长度必然 \(\geq i+1\),所以 \(\sum ans\) 是 \(O(n \ln n)\) 级别的。
考虑一下我们能不能直接找出这些段。
那么首先枚举 \(i\),然后按照以下方式贪心。
记上一次选的段是 \([x,las]\),\(o\) 的下一个 \(1\) 是 \(\text{next}(o)\)。
我们贪心的去想肯定希望 \([las+1,y]\) 的 \(y\) 最大,找到这么一个 \(y\) 容易 \(O(1)\) 实现。
考虑这样会出现的问题,如果 \([las+1,las+i]\) 里面全是 \(0\),那么我们需要进行一个调整,使得左边的一部分 \(0\) 被分到上一段。
我们可以对于前面的段都记下来,首先一个段如果只有一个 \(1\),那么我们做不到对这个段进行调整。
考虑上一个有 \(\geq 3\) 个 \(1\) 的段,分裂出最后两个 \(1\),接下来讨论一点细节。
现在序列长这样:\(\dots 1 \dots 1\:s_1\:s_2\:s_3\dots 0,0,0,0,0,0,0,0\)。
其中 \(s_i\) 是一个只有一个 \(1\) 的段,记第一个 \(1\) 的位置是 \(p\),第二个是 \(q\),那么考虑以下事情。
我们必然会在 \(p-1\) 之前进行一次分裂,不然相当于没有调整。
考虑如果我们将 \(p,q,\text{next}(q)\) 分成一段(不妨假设它们可以),那么 \(\text{next}(q)\) 后面会空出来若干个 \(0\),如果没有那么相当于没有调整,那这样就寄了,甚至不如原来的。
那么也就是说肯定要分成 \([p,q-1]\) 的。
而且这样还使 \(q\) 在它们段的第一个,能取掉后面尽可能多的 \(0\)。
如果 \(q,\text{next}(q),\text{next(next(}q\text{))}\) 能放在一段的话,那么你就出事了,说明 \(\text{next(next(}q\text{))}\) 是在它们段的第一个,那么调整其实没用。
然后你发现,我们似乎直接令 \(las \to q-1\) 就行了,然后更新一下答案。
分析一下时间复杂度:
如果这次调整成功了,接下来又遇到一个全 \(0\) 段,那么 \(q' >q\) 是必然的,如果不存在 \(q'>q\) 的那么这次调整必然失败,所以我们可以 \(las \to q-1\),\(q \to 0\)。
然后时刻维护 \(las,q,ans\) 即可。
最坏情况你的 \(las\) 指针会扫过每一个位置两次,所以复杂度还是 \(O(n \ln n)\)。
放个代码可能好理解一些:
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 2e6+5;
char s[MAXN];
int n, pos[2], res[MAXN];
int pre[MAXN], l[MAXN][2], L[MAXN];
inline int calc(int x){
int now=0, r, o, ans=0, pos, las=-1, lasans;
while(now<n){
r=min(n,now+x);
o=l[r][(pre[now]&1)^1];
if(o==-1 || o<=now){
if(las==-1) return -1;
pos=L[las+1];
ans=lasans+1; now=pos-1; las=-1;
continue;
}
if(pre[o]-pre[now]>=2) las=o, lasans=ans+1;
now=o; ans++;
}
return ans;
}
inline void solve(){
scanf("%s",s+1); n=strlen(s+1);
for(int i=1;i<=n;++i) pre[i]=pre[i-1]+(s[i]=='1');
pos[0]=0; pos[1]=-1; int p=0;
for(int i=1;i<=n;++i) L[i]=p, pos[pre[i]&1]=i, l[i][0]=pos[0], l[i][1]=pos[1], p=s[i]=='1'?i:p;
for(int i=1;i<=n;++i) printf("%d ",calc(i)); putchar(10);
}
int main(){
//freopen("partition.in","r",stdin);
//freopen("partition.out","w",stdout);
int t; scanf("%d",&t);
while(t--) solve();
return 0;
}

浙公网安备 33010602011771号