【洛谷P1484】种树【堆】【贪心】
题目大意:
题目链接:https://www.luogu.org/problemnew/show/P1484
有个点,选择其中互不相邻的不超过个点,使得点权和最大。
思路:
思维题。
考虑贪心。如果我们第一次选择了最大值点,那么选择两个点时,要么点和点一起选,要么两个都不选。
如果我们选择点和点,那么贪心思想,必然大于任意。但是当时,肯定小于(因为一开始是最大的)。矛盾。
证毕
如果不选择和,那么就是一个正常的贪心。但是如果选择和的话,就需要满足可撤销。
如果我们把的值更改成,再次选择数组中最大值,那么就等于!
这样用堆维护最大值,就可以做到的复杂度
代码:
#include <queue>
#include <cstdio>
#define mp make_pair
using namespace std;
typedef long long ll;
const int N=500010;
int n,m;
bool p[N];
ll a[N],ans;
priority_queue<pair<ll,int> > q;
struct node
{
int l,r;
}link[N];
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
q.push(mp(a[i],i));
link[i].l=i-1; link[i].r=i+1;
}
while (m--)
{
while (p[q.top().second]) q.pop();
if (q.top().first<0) break;
ans+=q.top().first;
int id=q.top().second;
a[id]=a[link[id].l]+a[link[id].r]-a[id];
p[link[id].l]=p[link[id].r]=1;
link[id].l=link[link[id].l].l; link[link[id].l].r=id;
link[id].r=link[link[id].r].r; link[link[id].r].l=id;
q.pop(); q.push(mp(a[id],id));
}
printf("%lld",ans);
return 0;
}