问题描述
解题思路
非零段数量的计算
????在数组
A
A
A的开头和结尾处各加一个
0
0
0,可以清楚地看出:每一个非零段数量的结尾都与0紧邻 。
非零段数量的更新
????正整数
p
p
p的取值范围 为
A
1
+
1
,
A
2
+
1
,
…
…
A
n
+
1
A_1+1,A_2+1,……A_n+1
A1?+1,A2?+1,……An?+1去重后的集合。
p
p
p取其他值的效果最终会与取上述值的效果一致。 ????我们将
A
1
+
1
,
A
2
+
1
,
…
…
A
n
+
1
A_1+1,A_2+1,……A_n+1
A1?+1,A2?+1,……An?+1排序 、去重 后的结果记作:
1
≤
a
1
+
1
<
a
2
+
1
<
…
…
<
a
k
+
1
,
a
i
(
1
≤
i
≤
k
)
∈
A
1\le a_1+1<a_2+1<……<a_k+1,a_i(1\le i\le k) \in A
1≤a1?+1<a2?+1<……<ak?+1,ai?(1≤i≤k)∈A ????同时,
p
p
p取
a
i
+
1
(
1
≤
i
≤
k
)
a_i+1(1\le i\le k)
ai?+1(1≤i≤k)得到的非零段数量
P
e
r
i
o
d
N
u
m
i
PeriodNum_{i}
PeriodNumi?可以在
p
p
p取
a
i
?
1
+
1
a_{i-1}+1
ai?1?+1得到的非零段数量
P
e
r
i
o
d
N
u
m
i
?
1
PeriodNum_{i-1}
PeriodNumi?1?上得到,这样可以避免重复计算 。 ????我们只需要在
p
p
p取
a
i
?
1
+
1
a_{i-1}+1
ai?1?+1得到的数组A的基础上,将
a
i
a_i
ai?依次替换为
0
0
0。并根据以下规则 (以
a
i
=
1
a_i=1
ai?=1为例)由
P
e
r
i
o
d
N
u
m
i
?
1
PeriodNum_{i-1}
PeriodNumi?1?得到
P
e
r
i
o
d
N
u
m
i
PeriodNum_i
PeriodNumi?:
AC代码
#include <iostream>
#include <vector>
#include <set>
#include <map>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<int> A;
set<int> DiffNumList;
map<int, vector<int>> NumPos;
A.push_back(0);
for (int i = 1; i <= n; ++i)
{
int Num;
cin >> Num;
A.push_back(Num);
DiffNumList.insert(Num);
NumPos[Num].push_back(i);
}
int PeriodNum = 0;
A.push_back(0);
for (int i = 1; i <= n; ++i)
{
if (A[i] != 0 && A[i + 1] == 0)
{
++PeriodNum;
}
}
int maxPeriodNum = PeriodNum;
for (int Num : DiffNumList)
{
if (Num == 0)
continue;
for (int i = 0; i < NumPos[Num].size(); ++i)
{
int beginIndex = NumPos[Num][i], endIndex = beginIndex;
if (A[beginIndex] == 0)
continue;
while (A[endIndex] == Num)
{
A[endIndex] = 0;
++endIndex;
}
endIndex -= 1;
if (A[beginIndex - 1] == 0 && A[endIndex + 1] == 0)
--PeriodNum;
else if (A[beginIndex - 1] != 0 && A[endIndex + 1] != 0)
++PeriodNum;
}
maxPeriodNum = max(PeriodNum, maxPeriodNum);
}
cout << maxPeriodNum << endl;
return 0;
}
|