zoukankan      html  css  js  c++  java
  • 数据备份

    147. 数据备份

    算法进阶上的题是真的毒瘤..

    知到打完(抄题解)代码,才貌似理解了一丢丢....惭愧...

    让我们重新理一下思路,这种题就是看到题,不会思路,会思路不会写的题目,所以我们要慢慢来...

    首先我们需要搞点性质...第一直觉,最短的距离和,应该不会有跨过某个点去找其他的点吧,因为如果存在这样的方案,显然与周围的点配对要更优...于是乎我们知道一个点如果要对答案产生贡献,必然是与周围的点配对的..

    可是这简陋的性质,好像不能支撑我们做这个题目...没办法,继续挖掘性质...

    这里就直接将结论放上去了:如果存在一个区间,去建立的每个点都是与周围点配对,如果再多选一条边,如果最优解要破坏其中的情况,那么必然吗是全部破坏的...

    见图:我们要选择虚线的话,也就是要破坏实线,最优解一定满足虚线全部选..

    首先当我们k==2的情况,(k==1我们直接选最小的边即可).

    图中蓝色实线为我们k==1的选择,如果此时k==2最优解绿色,即我们破坏了实线,但却选择了并非相邻的区域,我们看看是否有什么矛盾.由于蓝色线咸鱼绿色线,所以我们选择蓝线与右边的绿线一定由于现在两条绿线的选择,所以绿色的线为最优解矛盾.

    之后我们直接拓展到k的情况,即知道了k-1的最优解为连续的情况,看结论是否任然成立.

    我们看蓝色为上一个的最优解,绿线是应该到达的轨迹.如果我们假设最优解不是这,也就是起码有一条绿线跑去其他的位置了,如图中红色线的位置.我们发现红线和蓝线,绿线没有交集,也就是说红线可以加到绿线和蓝线的任一个集合中.

    而此时比较蓝线和绿线,由于蓝线是上一次的最优解,所以在抛去红线的k-1个绿线的权值大于蓝线,而此时的最优解显然是蓝线+红线,与绿线是最优解矛盾..

    此时我们又发现一个性质,即如果再一段连续的线中,要么选择与他毫不相及的边,如果选的边有交集,那一定是将原本的连续得全部破坏才有可能是最优解...

    那们我们就可以做这道题了,首先我们将边化点,点权为相邻边的距离.

    之后我们思考要用到的数据结构,我们要在当前选择一个最优决策,然后修改状态,加入下一个决策.用set和堆都行...

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N=100010;
    int n,k,l[N],r[N];
    ll s[N];
    set<pair<ll,int> >se;
    set<pair<ll,int> >::iterator it;
    inline void del(int p)
    {
        r[l[p]]=r[p];
        l[r[p]]=l[p];
    }
    int main()
    {
        cin>>n>>k;
        for(int i=0;i<n;++i) cin>>s[i];
        for(int i=n-1;i>=1;--i) s[i]-=s[i-1];
        s[0]=s[n]=1e15;
       for(int i=0;i<=n;++i)
       {
           l[i]=i-1;
           r[i]=i+1;
           if(i>=1&&i<n) se.insert({s[i],i}); 
       }
       ll ans=0;
       while(k--)
       {
           it=se.begin();
           ll v=it->first;
           int p=it->second;int left=l[p],right=r[p];
           del(left);del(right);
           se.erase(it);se.erase({s[left],left});se.erase({s[right],right});
           s[p]=s[left]+s[right]-s[p];
           se.insert({s[p],p});
           ans+=v;
           
       }
       printf("%lld",ans);
       return 0;
    }
    View Code
  • 相关阅读:
    Fedora/CentOS/RHEL删除旧的内核
    Linux下使Shell命令脱离终端运行
    保持tmux窗口名更改后不变
    Centos7 修改ssh 默认端口号
    验证码生成代码
    Json帮助类代码
    Http请求代码
    cookies读写代码
    缓存读写代码
    数据读写 CommonCurd
  • 原文地址:https://www.cnblogs.com/gcfer/p/12693995.html
Copyright © 2011-2022 走看看