zoukankan      html  css  js  c++  java
  • Luogu P3620 [APIO/CTSC 2007]数据备份

    题目
    凸优化选手往后稍稍。
    显然我们是选择(k)对相邻的,所以我们可以差分后将题意转化为选(k)个不相邻的数使其和最小。
    我们考虑一个贪心:每次选最小的。这个贪心的错误性是显然的。
    我们加入一个反悔机制:
    取走一个数(a)之后,我们把它旁边的两个数(b,c)去掉,在这个位置放一个新的数(b+c-a)
    然后我们用堆维护最小值,用链表维护旁边的数,再开个桶记录某个位置的数是否被删即可。
    如何理解这个贪心的正确性呢:如果你不选择一个当前最小的点,那么你是为了选择它旁边的两个点。
    自己随便想想就能理解了。

    #include<bits/stdc++.h>
    using namespace std;
    const int N=100007,inf=0x3f3f3f3f;
    struct node{int v,p;}t;
    int operator<(node a,node b){return a.v>b.v;}
    int f[N],l[N],r[N],v[N];
    priority_queue<node>q;
    void del(int x){l[x]=l[l[x]],r[x]=r[r[x]],r[l[x]]=x,l[r[x]]=x;}
    int read(){int x;scanf("%d",&x);return x;}
    int main()
    {
        int n=read(),m=read(),i,ans=0,p;
        for(i=0;i<n;++i) v[i]=read();
        for(i=n-1;i;--i) v[i]-=v[i-1],l[i]=i-1,r[i]=i+1,q.push((node){v[i],i});
        v[0]=v[n]=inf;
        for(i=1;i<=m;++i)
        {
    	while(f[q.top().p]) q.pop();
    	t=q.top(),q.pop(),p=t.p,ans+=t.v,f[l[p]]=f[r[p]]=1,v[p]=v[l[p]]+v[r[p]]-v[p],q.push((node){v[p],p}),del(p);
        }
        return !printf("%d",ans);
    }
    
  • 相关阅读:
    洛谷 P5043 树的同构 题解
    CF 1178E Archaeology 题解
    UVA 1642 MagicalGCD 题解
    洛谷 P3919 可持久化线段树 题解
    SPOJ 4003 Phone List 题解
    OI/ACM最全卡常大招
    洛谷 P3368 树状数组 题解
    逆序对
    洛谷 U78696 图书馆馆长的考验 题解
    原创 疲劳炉石传说
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/11580347.html
Copyright © 2011-2022 走看看