zoukankan      html  css  js  c++  java
  • 洛谷P1484 种树&洛谷P3620 [APIO/CTSC 2007]数据备份 题解(堆+贪心)

    洛谷P1484 种树&洛谷P3620 [APIO/CTSC 2007]数据备份 题解(堆+贪心)

    标签:题解
    阅读体验:https://zybuluo.com/Junlier/note/1329957

    题目链接地址:
    洛谷P1484 种树
    洛谷P3620 [APIO/CTSC 2007]数据备份各大oj多倍经验

    照例吐槽

    两道基本一模一样的题,只是第二道要差分顺便思维稍微向这边转化一下。。。
    我觉得这两个题思维很不错啊!很(Noip T2)的样子。。。

    话不多说将题解

    贪心+堆优化
    肯定一开始想到一个(O(nk))(dp)是吧,发现跑不过又优化不了。。。
    那和(dp)最相近而且时间复杂度低的算法就是贪心了罗。。。
    下面以洛谷P1484 种树为题目来讲,洛谷P3620 [APIO/CTSC 2007]数据备份的话自己(yy)改一下就过啦

    不用想了,每次直接选最大值肯定是错误的。。。
    那怎么办?贪心不是有后悔操作嘛!

    我们还是直接贪心选最大的,考虑怎么后悔,是不是与选(v[i])相对的就是选(v[i-1],v[i+1]),那么对于一次后悔,我们可以看做选了(v[i])后,(Ans+=v[i]),并且后面我们又选了一个(v[i-1]+v[i+1]-v[i]),算一下发现最终就是(Ans+=v[i+1]+v[i-1])是吧,所以我们可以考虑直接把(v[i])的值修改了之后可能重新选一遍

    那么怎么实现这些操作呢(口糊谁不会。。
    一般这种最大最小加东西删东西的就可以想到堆啦

    考虑用一个大根堆来贪心,每次选出一个最大的元素,然后显然我们要把这个元素两边的元素标记为不能选是吧,那就标记一下呗(因为我们会修改(v[i])的值,所以无所顾忌这两个东西是否还存在,有点难理解。。。)

    然后我们发现当我们修改了元素的值之后,他影响到的左右是不同的,所以我们还需要一个可以支持动态修改左右元素的数据结构,显然的不就是双向链表嘛。。。

    那就做完了

    代码

    压行永远是看代码的人的噩梦,写代码的人的幸福。。。
    洛谷P1484 种树

    #include<bits/stdc++.h>
    #define il inline
    #define rg register
    #define ldb double
    #define lst long long
    #define rgt register int
    #define N 500050
    using namespace std;
    const int Inf=1e9;
    il int MAX(rgt x,rgt y){return x>y?x:y;}
    il int MIN(rgt x,rgt y){return x<y?x:y;}
    il int read()
    {
        int s=0,m=0;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')m=1;ch=getchar();}
        while( isdigit(ch))s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
        return m?-s:s;
    }
    
    int n,K;lst Ans;
    int v[N],le[N],ri[N],vis[N];
    struct NODE{int id,w;};
    priority_queue<NODE> H;
    bool operator<(const NODE&a,const NODE&b){return a.w<b.w;}
    
    int main()
    {
        n=read(),K=read();
        for(rgt i=1;i<=n;++i)
        {
            v[i]=read(),le[i]=i-1,ri[i]=i+1;
            H.push((NODE){i,v[i]});
        }
        for(rgt i=1,l,r;i<=K;++i)
        {
            while(!H.empty()&&vis[H.top().id])H.pop();
            rg NODE tmp=H.top();H.pop();if(tmp.w<0)break;
            Ans+=tmp.w,l=le[tmp.id],r=ri[tmp.id];
            v[tmp.id]=v[l]+v[r]-v[tmp.id];
            ri[le[l]]=ri[l],le[ri[l]]=le[l],le[l]=ri[l]=0;
            ri[le[r]]=ri[r],le[ri[r]]=le[r],le[r]=ri[r]=0;
            vis[l]=vis[r]=1,H.push((NODE){tmp.id,v[tmp.id]});
        }return printf("%lld
    ",Ans),0;
    }
    

    洛谷P3620 [APIO/CTSC 2007]数据备份
    需要注意的是:因为变成了最小值,所以边界可能会减出负数,所以处理下边界。。。

    #include<bits/stdc++.h>
    #define il inline
    #define rg register
    #define ldb double
    #define lst long long
    #define rgt register int
    #define N 100050
    using namespace std;
    const int Inf=1e9;
    il int MAX(rgt x,rgt y){return x>y?x:y;}
    il int MIN(rgt x,rgt y){return x<y?x:y;}
    il int read()
    {
        int s=0,m=0;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')m=1;ch=getchar();}
        while( isdigit(ch))s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
        return m?-s:s;
    }
    
    int n,K;lst Ans;
    int v[N],le[N],ri[N],vis[N];
    struct LINE{int id,x;};
    priority_queue<LINE> H;
    bool operator<(const LINE&a,const LINE&b){return a.x>b.x;}
    
    int main()
    {
        n=read(),K=read();
        for(rgt i=1;i<=n;++i)v[i]=read();
        for(rgt i=1;i<n;++i)
        {
            v[i]=v[i+1]-v[i];
            le[i]=i-1,ri[i]=i+1;
            H.push((LINE){i,v[i]});
        }v[0]=v[n]=Inf;
        for(rgt i=1,l,r;i<=K;++i)
        {
            while(!H.empty()&&vis[H.top().id])H.pop();
            rg LINE tmp=H.top();H.pop();
            Ans+=tmp.x,l=le[tmp.id],r=ri[tmp.id];
            v[tmp.id]=v[l]+v[r]-v[tmp.id];
            ri[le[l]]=ri[l],le[ri[l]]=le[l],le[l]=ri[l]=0;
            ri[le[r]]=ri[r],le[ri[r]]=le[r],le[r]=ri[r]=0;
            vis[l]=vis[r]=1,H.push((LINE){tmp.id,v[tmp.id]});
        }return printf("%lld
    ",Ans),0;
    }
    
  • 相关阅读:
    Android应用程序组件Content Provider在应用程序之间共享数据的原理分析
    Android录制声音(二)录音输输出格式
    Firemacs:像垄断 Emacs 一样垄断 Firefox
    超棒的 KDE 面板小序次-Kirocker Music Display
    特征化设置你的linux环境
    软响铃 ── 把 beep 换成音乐
    简化 Picasa 图片上传
    Moonlight:Linux 平台上的 Silverlight
    Wine 0.9.39
    本钱与linux
  • 原文地址:https://www.cnblogs.com/cjoierljl/p/9892457.html
Copyright © 2011-2022 走看看