結果
| 問題 |
No.1437 01 Sort
|
| ユーザー |
tyawanmusi
|
| 提出日時 | 2021-02-20 16:23:57 |
| 言語 | Python3 (3.13.1 + numpy 2.2.1 + scipy 1.14.1) |
| 結果 |
TLE
|
| 実行時間 | - |
| コード長 | 2,211 bytes |
| コンパイル時間 | 250 ms |
| コンパイル使用メモリ | 12,800 KB |
| 実行使用メモリ | 27,188 KB |
| 最終ジャッジ日時 | 2024-09-19 01:14:06 |
| 合計ジャッジ時間 | 4,316 ms |
|
ジャッジサーバーID (参考情報) |
judge4 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 10 TLE * 1 -- * 13 |
ソースコード
# writer 解
# O(N log^2 N)
# にぶたんしてくれるやつ
from bisect import bisect_left, bisect_right
n = int(input())
s = input()
ans = 10**10
zero = s.count("0")
one = n-zero
if zero == 0 or zero == n:
exit(print(0))
# 注意事項
out = [0]*n
if s[0] == "1":
out[0] = 1
for i in range(n-1, -1, -1):
if s[i] == "1":
out[i] = 1
else:
break
# "1" である index をとりあえずいっぱい列挙
bit = []
for i in range(n):
if s[i] == "1":
bit += [i, i+n, i+n+n, i+n+n+n]
bit.sort()
def f(l, ll):
# bit[ll, ll+one) を [l, l+one) に揃えるとき、どれだけグルグル回るか
#注意事項
sp_l = (l+one)%n
sp_r = n
if sp_l == 0:
sp_l = n
ansl = 0
if bit[ll] <= l+n:
# 注意事項
# ((x-1)%n+1) で 0...n-1 ではなく 1...n にする
if sp_l <= ((bit[ll]-1)%n+1) <= sp_r and out[bit[ll]%n] == 0:
ansl = l+n-bit[ll]-1
else:
ansl = l+n-bit[ll]
ansr = 0
if l+n+one-1 < bit[ll+one-1]:
# "右側" である要素を数えるにぶたん
ng = -1
ok = one
while ng+1 != ok:
mid = (ng+ok)//2
if l+n+mid < bit[ll+mid]:
ok = mid
else:
ng = mid
# 注意事項
flag1 = True
flag2 = False
x = l+n+ok
if x%n != 0:
x += n-(x%n)
if x <= l+n+one-1:
if l+n+ok <= bit[ll+ok] <= x:
flag2 = True
x += n
if l+n+ok <= bit[ll+ok] <= x:
flag1 = False
ansr = one-ok
ansr += flag1
ansr -= flag2
return max(ansl, ansr)
# 目標の区間を全探索
for l in range(n):
# グルグル回る以前の操作回数
anss = (-l-one)%n
# 注意事項
sp_l = (l+one)%n
sp_r = n
if sp_l == 0:
sp_l = n
# 何回グルグル回れば揃えられるかにぶたん
ng = -1
ok = n
while ng+1 != ok:
mid = (ng+ok)//2
# 回る回数を決め打ちし、bit[ll, ll+one) の ll をできるだけ小さくする
# 注意事項
x = l+n-mid-1
if not(sp_l <= ((x-1)%n+1) <= sp_r and out[x%n] == 0):
x += 1
ll = bisect_left(bit,x)
if f(l, ll) <= mid:
ok = mid
else:
ng = mid
ans = min(ans, anss+ok*n)
print(ans)
tyawanmusi