• luogu1484 种树


    题目大意:

    给定一个大小为n的序列$ a_1,a_2,a_3...a_n $,问从中选至多k个不相邻的数(可以小于k个),权值和最大为多少。

    解题方法:

    考虑选取一个数对其两边的影响,当选了$ a_p $时,p位置左侧的数和右侧的数都无法选,但存在一种决策,即放弃$ a_p $,选择$ a_pl $和$ a_pr $,为实现这一操作,可用链表,每次选出$ a_p $后,将 $ a_pl+a_pr-a_p $ 填在p位置并更新左右指针,每次从中选最大的数,用堆维护即可。

    代码:

     1 #include<bits/stdc++.h>
     2 #define ll long long
     3 #define del(a,b) memset(a,b,sizeof(a))
     4 using namespace std;
     5 const int MAXN=5e5+10;
     6 int n,k;
     7 bool vis[MAXN];
     8 ll a[MAXN],l[MAXN],r[MAXN];
     9 struct Node
    10 {
    11     ll val;int id;
    12     Node(ll a,int b):val(a),id(b){}
    13     friend bool operator <(const Node &a,const Node &b){return a.val<b.val;}
    14 };
    15 priority_queue<Node> Q;
    16 template <class T>void read(T &x)
    17 {
    18     bool f=0;char ch=getchar();x=0;
    19     for(;ch<'0' || ch>'9';ch=getchar())if(ch=='-') f=1;
    20     for(;ch>='0' && ch<='9';ch=getchar())x=x*10+ch-'0';
    21     if(f) x=-x;
    22 }
    23 int main()
    24 {
    25     read(n);read(k);
    26     for(int i=1;i<=n;i++)
    27     {
    28         read(a[i]);l[i]=i-1;r[i]=i+1;
    29         Q.push(Node(a[i],i));
    30     }
    31     ll ans=0;
    32     for(int i=1;i<=k;i++)
    33     {
    34         while(vis[Q.top().id]) Q.pop();
    35         Node now=Q.top();Q.pop();
    36         if(now.val<0) break;
    37         ans+=now.val;int p=now.id;
    38         a[p]=a[l[p]]+a[r[p]]-a[p];
    39         Q.push(Node(a[p],p));
    40         vis[l[p]]=vis[r[p]]=1;
    41         l[p]=l[l[p]];r[l[p]]=p;
    42         r[p]=r[r[p]];l[r[p]]=p;
    43     }
    44     printf("%lld",ans);
    45     return 0;
    46 }
    View Code
  • 相关阅读:
    Linux源码Kconfig文件语法分析
    从0移植uboot (一) _配置分析
    ARM汇编与C混合编程
    ARM汇编程序结构
    ARMGNU伪指令
    Linux tcp黏包解决方案
    Linux 服务器模型小结
    Linux IPC udp/tcp/UNIX域 socket编程
    Linux IPC socket 广播,组播
    Linux I/O多路复用
  • 原文地址:https://www.cnblogs.com/Oracle-LinJH/p/9820396.html
Copyright © 2020-2023  润新知