题解 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)


posted @ 2022-09-15 14:26  雪之下,树之旁  阅读(32)  评论(0编辑  收藏  举报