1 条题解

  • 0
    @ 2025-8-24 22:39:58

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar chen_zhe
    Aya 敲可爱的~

    搬运于2025-08-24 22:39:58,当前版本为作者最后更新于2022-09-10 20:54:39,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    根据题目描述,首先可以证明的是,选取的 ai1a_i \neq 1 的点的个数不会大于等于 33

    这是因为,当选取了 ai1a_i \neq 1 的节点数量恰为 22 的时候,只有一种在左侧位置 ll 选择一个 ai=2a_i=2 的节点,在右侧位置 rr 选择一个 ai=3a_i=3 的节点的情况下不会产生冲突(即,存在方案使得选出的点集是个独立集)。此时若是再选择一个 ai1a_i \neq 1 的节点,例如说在 l<x<rl<x<r 的位置 xx 选择一个 ai=2a_i=2,则无法和 ll 位置上的节点构成独立集;选择 ai=3a_i=3,则无法和 rr 位置上的节点构成独立集。其余四种情况(1x<l1 \leq x<lr<xnr<x \leq n)同理。

    因此得出,选择的节点中,ai1a_i \neq 1 的节点个数为 0,1,20,1,2。若一个 ai1a_i \neq 1 的都不选,就是都选择 ai=1a_i=1 的节点,这个时候构成的独立集在这个情况下是最大的。

    若选择一个 ai1a_i \neq 1 的节点,就会分成两个情况。若选择一个 ai=2a_i=2 的节点,即向所有编号 <i<i 的节点连边,我们希望在这个情况下被连边连接到的 ai=1a_i=1 的节点最少。因此我们让这个 ai=2a_i=2 的节点选择的尽可能靠左,这样其右边的 ai=1a_i=1 的节点都是可选放入独立集的;对于选择一个 ai=3a_i=3 的情况是同理的。

    若选择两个 ai1a_i \neq 1 的节点,如上文所述,只有一种在左侧位置 ll 选择一个 ai=2a_i=2 的节点,在右侧位置 rr 选择一个 ai=3a_i=3 的节点的情况下不会产生冲突,这个时候在 l<x<rl<x<r 范围内的 ax=1a_x=1 都是可选择放入独立集的。

    综上所述,我们所选取的节点有如下可能:

    • 选取所有 ai=1a_i=1 的点;
    • 选取最左边的 ai=2a_i=2 的点,再选取所有其右边的 ai=1a_i=1 的点;
    • 选取最右边的 ai=3a_i=3 的点,再选取所有其左边的 ai=1a_i=1 的点;
    • 选取最左边的 ai=2a_i=2 的点和最右边的 ai=3a_i=3 的点,再选取所有其中间的 ai=1a_i=1 的点。

    四种情况分别讨论一下看哪一个选取的点更多。注意第四种情况下需要判断最左边的 ai=2a_i=2 的点和最右边的 ai=3a_i=3 的点的位置,否则容易被如下数据卡住(正确答案是 11):

    2
    3 2
    

    参考代码:

    #include <iostream>
    
    using namespace std;
    
    int n,a[100050],l,r;
    
    int main()
    {
    	cin >> n;
    	for (int i=1;i<=n;i++)
    		cin >> a[i];
    	for (int i=1;i<=n;i++)
    	{
    		if (a[i]==2)
    		{
    			l=i;
    			break;
    		}
    	}
    	for (int i=n;i>=1;i--)
    	{
    		if (a[i]==3)
    		{
    			r=i;
    			break;
    		}
    	}
    	int ans=0;
    	if (l)
    	{
    		int ret=1;
    		for (int i=l+1;i<=n;i++)
    			ret+=(a[i]==1);
    		ans=max(ans,ret);
    	}
    	if (r)
    	{
    		int ret=1;
    		for (int i=1;i<=r-1;i++)
    			ret+=(a[i]==1);
    		ans=max(ans,ret);
    	}
    	if (l && r && r>l)//第四种情况的特判
    	{
    		int ret=2;
    		for (int i=l+1;i<=r-1;i++)
    			ret+=(a[i]==1);
    		ans=max(ans,ret);
    	}
    	int ret=0;
    	for (int i=1;i<=n;i++)
    		ret+=(a[i]==1);
    	ans=max(ans,ret);
    	cout << ans << endl;
    	return 0;
    }
    
    • 1

    信息

    ID
    7048
    时间
    1000ms
    内存
    128MiB
    难度
    3
    标签
    递交数
    0
    已通过
    0
    上传者