• 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;
    }
  • 相关阅读:
    转贴:Asp.Net 学习资源列表
    实现简单的写字板
    android绘图—Paint path 旋转
    Eclipse Android编程快捷键
    android Bitmap学习总结
    各种颜色对应的十六进制数
    Android surfaceView 与View 的区别
    SQLite设置_id自增的方法
    数据库表外键设置
    android自定义View的用法
  • 原文地址:https://www.cnblogs.com/smartljy/p/13431869.html
Copyright © 2020-2023  润新知