• ACwing 147 数据备份 贪心 set


    LINK:数据备份

    以前做过这种贪心 不过没有好好的证明 这次来严格的证明一下。

    不难发现 最后的答案 选择的所有两对公司必然相邻。

    所以排序后 把数组变成ai-ai-1. 这样问他的模型就是 n-1个数从中选出k个数 且任意两个数不能相邻 求和的最小值。

    k==1时显然是全局最小值。

    k==2的时候 有两种方法:全局最小值 和全局最小值不相邻的 最小数字。还有一种 把全局最小值扔了 选他们两边的数字。

    此时 选出全局最小值之后把左右两边元素给去掉 因为这两个决策假了。

    加入一个新决策 :两边元素之和-中间的元素。

    然后可以发现 此时决策集合完全覆盖了我们上述的分析。

    考虑拓展到k比较大的情况。

    我们不断维护决策集合的完整性。而且对于每一个局面都是一样的。所以从递归来看这是正确的。

    换个角度:从一个局面最优转到另一个局面 可以发现 此时如果我们选择了上次新决策那么符合我们前面的结论2.

    如果选择了其他元素符合前面的结论1.

    对于一个新局面来说其最优也是来自两个结论。

    综上 做出的所有决策都是 结论1和结论2的一种 这对于所有的局面都是最优的选择 所以是正确的。

    const int MAXN=100010;
    int n,k;
    ll ans;
    int l[MAXN],r[MAXN];
    ll w[MAXN];
    ll a[MAXN];
    multiset<pii>s;
    multiset<pii>:: iterator it,itt,itt1;
    int main()
    {
        //freopen("1.in","r",stdin);
        get(n);get(k);
        rep(1,n,i)get(a[i]);
        sort(a+1,a+1+n);
        rep(1,n-1,i)w[i]=a[i+1]-a[i],s.insert(mk(w[i],i)),l[i]=i-1,r[i]=i+1;
        w[0]=inf;w[n]=inf;s.insert(mk(w[0],0));s.insert(mk(w[n],n));
        while(k--)
        {
            it=s.begin();
            ans+=(*it).F;
            int x=(*it).S;
            int L=l[x];
            int R=r[x];
            s.erase(it);
            itt=s.find(mk(w[L],L));
            s.erase(itt);
            itt1=s.find(mk(w[R],R));
            s.erase(itt1);
            w[x]=w[R]+w[L]-w[x];
    		l[x]=l[L];r[x]=r[R];
    		r[l[L]]=x;l[r[R]]=x;
            s.insert(mk(w[x],x));
        } 
        putl(ans);
        return 0;
    }
    
  • 相关阅读:
    Java三大框架
    单例模式和工厂模式(百度文库)
    使用java代码编辑oracle数据库
    extends 与implements的区别和用法
    介绍MVC编程架构模式
    接口具体是什么东西
    Servlet和JSP的本质和区别
    用户注册,登录,留言系统
    页面跳转的五种方法
    cookie的长度和限制数量
  • 原文地址:https://www.cnblogs.com/chdy/p/12720526.html
Copyright © 2020-2023  润新知