• YbtOj练习:贪心4 修改序列


    看到数据范围,就想写一个线性复杂度的算法,一开始我是这样的:

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e5+5;
    int n,a[N],ans,b[N];
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        b[1]=a[1];
        for(int i=1;i<n;i++) b[i+1]=b[i]+i;
        for(int i=1;i<=n;i++) if(b[i]!=a[i]) ans++;
        cout<<ans;
        return 0;
    }

    提交后只有50分(数据太水了,竟然拿到了50分)

    这种做法显然是错误的,因为它只以1为基准构造了一个合法序列。例如当序列为

    1 5 7 10 14时,如果按照上述做法,合法序列为:1,2,4,7,11 要修改4处。但显然这里只要修改一处即可。

    于是就想到了正确的算法雏形:依次以每一个数为基准,统计修改次数,最后取最小值,就是正解。但显然这种做法是O(n^2)的,需要优化。

     则

    我们定义

    它得到的结果就是a[1]。

    我们只需要遍历一遍原数组,求出每一个数的f,如果f相同,则意味着它们对应的a[1]相同,即它们处于同一个合法序列中。我们只要求出最多的相同的f的个数,就是合法值的个数。答案就是n-cnt.

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e5+5;
    int n,a[N],f[N];
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        for(int i=1;i<=n;i++) 
        {
            f[i]=a[i]-(i-1)*i/2;
        }
        sort(f+1,f+n+1);
        int len=1,ans=0;
        for(int i=2;i<=n;i++)
        {
            if(f[i]!=f[i-1]) 
            {
                ans=max(ans,len);
                len=1;
            }
            else len++;
        }
        ans=max(ans,len);
        cout<<n-ans;
        return 0;
    }
  • 相关阅读:
    Mysql常见索引介绍
    Mysql字段修饰符(约束)
    使用select和show命令查看mysql数据库系统信息
    Mysql5.7数据库介绍
    对Mysql数据表本身进行操作
    各种修改Mysql字符集
    Mysql的安全配置向导命令mysql_secure_installation
    firewalld介绍
    CentOS7使用yum安装mysql5.7
    利用ASP.NET一般处理程序动态生成Web图像(转)
  • 原文地址:https://www.cnblogs.com/smartljy/p/13431869.html
Copyright © 2020-2023  润新知