洛谷1484 种树

本文介绍了一种使用贪心算法结合堆的数据结构解决特定序列取数问题的方法。问题要求从给定序列中选取不相邻的数,使得总和最大。通过每次选择当前最大值并更新序列的方式实现最优解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【题意】给出一个n个数的序列,要求取出互补相邻的m个数,使得它们的和最大。

【算法】贪心,堆

【题解】

  每次取出最大的a,并且把a[i]设为a[pre[i]]+a[nxt[i]]-a[i]

  这种做法类似于给贪心一个反悔的机会,这个反悔的机会实质上是扩大你选择数字的影响范围,一旦扩大就一定不会反悔,因为一定是最优的。

  每次选择一个数字相当于把原问题缩小范围,改成在n-1个数中选出m-1个数

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<queue>
 4 #define LL long long
 5 using namespace std;
 6 const int maxn=1000010;
 7 LL pre[maxn],nxt[maxn],a[maxn],n,m,x,ans=0;
 8 bool mark[maxn];
 9 priority_queue<pair<LL,LL>,vector<pair<LL,LL> > >q;
10 inline int read(){
11     int k=0,f=1; char c=getchar();
12     while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
13     while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
14     return k*f;
15 }
16 void del(int x){
17     mark[x]=1;
18     pre[nxt[x]]=pre[x]; nxt[pre[x]]=nxt[x];
19     pre[x]=nxt[x]=0;
20 }
21 int main(){
22     n=read(); m=read();
23     for(int i=1;i<=n;i++) a[i]=read(),q.push(make_pair(a[i],i));
24     if(m>n/2){puts("ERROR"); return 0;}
25     for(int i=1;i<=n;i++) pre[i]=i-1,nxt[i]=i+1; //pre[1]=n; nxt[n]=1;
26     for(int i=1;i<=m;i++){
27         while(mark[q.top().second]) q.pop();
28         int tmp=q.top().second; q.pop();
29         if(a[tmp]<0) break;
30         ans+=a[tmp];
31         a[tmp]=a[pre[tmp]]+a[nxt[tmp]]-a[tmp]; q.push(make_pair(a[tmp],tmp));
32         del(pre[tmp]); del(nxt[tmp]);
33     }
34     return printf("%lld\n",ans),0;
35 }
View Code

 

转载于:https://www.cnblogs.com/DriverLao/p/8035149.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值