JZOJ5372. 【NOIP2017提高A组模拟9.17】猫 链表+贪心+堆优化

27 篇文章 0 订阅
11 篇文章 0 订阅
这是一道关于环形链表的优化贪心算法问题。题目要求在不能取相邻节点的限制下,从环中选择1到n/2个节点,寻找最优解。传统的DP方法在此问题上可能无效,而使用大根堆进行优化的贪心策略则更为适用。每次选取堆顶节点,并更新其相邻节点的贡献,用链表维护动态删除过程。需要注意使用long long类型以避免溢出。此题与编译优化问题相似,但存在不同之处。
摘要由CSDN通过智能技术生成

题意:一个长度为n的环,每个点有贡献,取了一个就不能取他的相邻,问取1-n/2个的最优方案是多少。
DP可能会挂,我自己试了试好像会出点问题= =毕竟是环,如果类似这种问题,不能拆环一般就不要DP
于是考虑贪心,大根堆优化。其实这题可以算是堆优化贪心的典型例题了,每次取完堆顶以后把这个点的贡献改为这个点相邻的两个点的贡献-这个点的贡献,然后把相邻两个删掉,相当于再次取到这个点时就是撤销,就是把这个点去掉,然后选择相邻的两个点的贡献。因为涉及到动态删除,所以用链表维护。
注意开ll,被坑了QAQ。
luogu好像有一道差不多的题目,叫什么编译优化,就是没要求输出n/2次,所以那题水一点。。

#include<bits/stdc++.h>
using namespace std;
#define N 200010
#define LL long long
#define P make_pair
int n,t,l[N],r[N];
bool vis[N];
LL ans,a[N];
priority_queue< pair<LL,int> >q;
int input() {
    int f=1,g=0; char c=getchar();
    while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9') {g=g*10+c-'0';c=getchar();}
    return f*g;
}
int main() {
    freopen("cat.in","r",stdin);
    freopen("cat.out","w",stdout);
    n=input();
    for(int i=1;i<=n;i++) a[i]=input(),q.push(P(a[i],i));
    for(int i=1;i<=n;i++) l[i]=i-1,r[i]=i+1; l[1]=n,r[n]=1;
    for(int i=1;i<=n/2;i++) {
        while(vis[t=q.top().second]) q.pop();
        ans+=q.top().first,q.pop();
        vis[l[t]]=vis[r[t]]=1,a[t]=a[l[t]]+a[r[t]]-a[t];
        l[t]=l[l[t]],r[t]=r[r[t]],r[l[t]]=l[r[t]]=t;
        q.push(P(a[t],t)),printf("%lld\n",ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值