题目
https://jzoj.net/senior/#main/show/1795
小结
你绝对想不到这是一道贪心题!!
很恶心,想了很久。。。。
首先,我们看看这个数据:
10 4
0001000000
让你切4份对吧。我们只需要找o(n)扫一遍。
首先算前缀和,算出
—0001000000
S:1232345678
把“1”当做-1,把“0”当做1去算。
我们很显然可以发现,最终的答案是
|Snm
上取整对吧。
这一点清楚了,我们就记录l为上一个分开的地方。
于是当s[i]-s[l]<=ans 时
再看
__00|01000000
S:12|12123456
|s[n]−s[i]m
(上取整)<=ans
那么我们就直接切,这样就保证了字典序最小。
至于最大,只需要反过来做一遍就好了。。。。。
(^__^)
打了我好久>>>>
var
n,m,i,ans,l,k,m1:longint;
s:ansistring;
sum,ans1:array[0..5000000]of longint;
begin
readln(n,m);
m1:=m;
readln(s);
for i:=1 to length(s) do
if s[i]='1' then sum[i]:=sum[i-1]-1
else sum[i]:=sum[i-1]+1;
if sum[n]=0 then
begin
l:=0;
for i:=1 to n do
if sum[i]=0 then inc(l);
if l>=m then ans:=0
else ans:=1;
end
else
begin
ans:=trunc(abs(sum[n])/m);
if abs(sum[n]) mod m>0 then inc(ans);
end;
l:=0;
for i:=1 to n do
begin
if sum[i]-sum[l]<=ans then
begin
k:=trunc(abs(sum[n]-sum[i])/(m-1));
if abs(sum[n]-sum[i]) mod (m-1)>0 then inc(k);
if k<=ans then
begin
write(i-l,' ');
l:=i;
m:=m-1;
end;
end;
if m=1 then
begin
writeln(n-l);
break;
end;
end;
for i:=length(s) downto 1 do
if s[i]='1' then sum[i]:=sum[i+1]-1
else sum[i]:=sum[i+1]+1;
m:=m1;
if sum[1]=0 then
begin
l:=0;
for i:=1 to n do
if sum[i]=0 then inc(l);
if l>=m then ans:=0
else ans:=1;
end
else
begin
ans:=trunc(abs(sum[1])/m);
if abs(sum[1]) mod m>0 then inc(ans);
end;
l:=n+1;
for i:=n downto 1 do
begin
if sum[l]-sum[i]<=ans then
begin
k:=trunc(abs(sum[i]-sum[1])/(m-1));
if abs(sum[i]-sum[1]) mod (m-1)>0 then inc(k);
if k<=ans then
begin
inc(ans1[0]);
ans1[ans1[0]]:=l-i;
l:=i;
m:=m-1;
end;
end;
if m=1 then
begin
write(l-1,' ');
break;
end;
end;
for i:=ans1[0] downto 1 do
write(ans1[i],' ');
writeln;
end.