题解 P8538 「Wdoi-2」灵山之上神风起
其实不算太难,可以发现如下性质:
- 对于整个数列来说,最小的可能的最大独立集答案就是 1 的个数
- 对于 \(a_i = 2\) 的项来说,他只可能与\(j \in (i, n]\) 中的项组成独立集。
- 对于 \(a_i = 3\) 的项来说,他只可能与\(j \in [1, i)\) 中的项组成独立集
下面以 \(a_i = 2\) 的情况进行详细分析:
不妨从最后向前遍历数列。考虑下列情况:
-
\(2\) \(2\) \(2\) \(1\) \(3\) 在这种情况下,对于前三个 \(2\) 来说,\(1\) 和 \(3\) 都可以取。
-
\(2\) \(2\) \(2\) \(3\) \(1\) \(1\) 这种情况下,肯定是选取两个 \(1\) 最优。倘若只有一个 \(1\) 呢?同样的,我们直接选择 \(1\) 即可,也就是说 \(1\) 的优先级一定大于 \(3\)。
-
同时,我们当然只能选择一个 \(3\) 位于 \(2\) 的右侧。(易证)
\(a_i = 3\) 的情况跟以上全部相反即可。
经过这些情况的分析,这道题就很简单啦。前后扫描两边就过了。
(最近在从 \(C\)++ 转战 \(Python\), 于是上 \(Python\) 代码)
n = int(input())
a = list(map(int, input().split(" ")))
a.insert(0, 0)
ok = 0
ans = 0
ans = a.count(1) # 最小值: 1的个数
dp = [0 for i in range(int(2e5))]
for i in range(n, 0, -1):
if a[i] == 1:
ok = 1
dp[i] = dp[i + 1] + 1
if a[i] == 2:
dp[i] = dp[i + 1]
ans = max(ans, dp[i] + 1) # 针对 2 进行统计
if a[i] == 3:
dp[i] = dp[i + 1] # 不能进入队伍
if ok == 0:
dp[i] += 1
ok = 1
dp = [0 for i in range(int(2e5))]
ok = 0 # 再来一遍
for i in range(1, n + 1):
if a[i] == 1:
ok = 1
dp[i] = dp[i - 1] + 1
if a[i] == 2:
dp[i] = dp[i - 1]
if ok == 0:
dp[i] += 1
ok = 1
if a[i] == 3:
dp[i] = dp[i - 1]
ans = max(ans, dp[i] + 1)
print(ans)