2020 10.27 普及 T2 交换
题目描述
给一个长度为 n 的 01 序列
s
[
1
]
,
s
[
2
]
,
.
.
.
.
,
s
[
n
]
,
s[1],s[2],....,s[n],
s[1],s[2],....,s[n],现在可以至多进行 1 次如下操作:
选择
x
<
n
,
1
≤
x
<
n
x < n,1≤x<n
x<n,1≤x<n,将 s 序列变成
s
[
x
+
1
]
,
s
[
x
+
2
]
,
.
.
.
.
.
s
[
n
]
,
s
[
1
]
,
s
[
2
]
,
.
.
.
.
s
[
x
]
s[x+1],s[x+2],.....s[n],s[1],s[2],....s[x]
s[x+1],s[x+2],.....s[n],s[1],s[2],....s[x]
输出最长的全为 1 的子区间长度。
输入描述:
一个 01 字符串,表示序列 s s s。( 1 < = ∣ s ∣ < = 100000 1<= |s| <= 100000 1<=∣s∣<=100000)
输出描述:
输出一个整数表示答案。
示例1
输入
1001
输出
2
示例2
输入
11111
输出
5
示例3
输入
10111010
输出
3
分析:用数组 f f f记录1的个数。具体操作:设 f [ i ] f[i] f[i]表示以第i个数为结尾的全是1 的最长区间的长度
显然有
f
[
i
]
{
s
[
i
]
=
0
f
[
i
]
=
0
s
[
i
]
=
1
f
[
i
]
=
f
[
i
−
1
]
+
1
f[i]\begin{cases} s[i]=0& \text{$f[i]=0$}\\ s[i]=1& \text{$f[i]=f[i-1]+1$} \end{cases}
f[i]{s[i]=0s[i]=1f[i]=0f[i]=f[i−1]+1
然后找到
m
a
x
(
f
[
i
]
)
max(f[i])
max(f[i]) 记为
m
a
x
n
maxn
maxn
接着分析交换后的长度:设为
a
n
s
,
a
n
s
=
0
ans,ans=0
ans,ans=0
设有变量
t
l
,
有
f
[
t
l
−
1
]
=
t
l
−
1
tl,有f[tl-1]=tl-1
tl,有f[tl−1]=tl−1:
显然,有
a
n
s
{
f
[
1
]
=
0
a
n
s
=
m
a
x
n
;
f
[
1
]
=
1
a
n
s
=
m
i
n
(
m
a
x
(
f
[
l
e
n
]
+
f
[
t
l
−
1
]
,
m
a
x
n
)
,
l
e
n
)
ans\begin{cases} f[1]=0& \text{$ans=maxn;$}\\ f[1]=1& \text{$ans=min(max(f[len]+f[tl-1],maxn),len)$} \end{cases}
ans{f[1]=0f[1]=1ans=maxn;ans=min(max(f[len]+f[tl−1],maxn),len)
a
n
s
ans
ans即为答案
c o d e : code: code:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
//#define r register
#define rep(i,x,y) for(int i=x;i<=y;++i)
#define per(i,x,y) for(int i=x;i>=y;--i)
using namespace std;
typedef long long ll;
string s;
int a[101010],len,f[100010],ans=-222;
int main()
{
cin>>s;
len=s.length();
rep(i,0,len-1)
a[i+1]=s[i]-'0';
rep(i,1,len)
{
if(a[i]==1)
{
f[i]++;
int tl=i+1;
while(tl<=len&&a[tl]==1)
f[tl]=f[tl-1]+1,++tl;
i=tl;
}
}
rep(i,1,len)
if(ans<f[i]) ans=f[i];
if(f[1]>0)
{
int tl=2;
while(tl<=len&&f[tl]>0) ++tl; //求tl
ans=max(f[len]+f[tl-1],ans);
ans=min(ans,len);
}
cout<<ans;
return 0;
}
T h a t ′ s That's That′s o k ok ok