P1484 种树
P1484 种树
题意:
在n个数中选出至多k个数,且两两不相邻,并使所选数的和最大。 n<=500000
思路
- 先建一个堆,把所有点扔进去,当取出队首元素时累加到答案时,把它和它左右两个点一起看成一个点,权值为a[l]+a[r]-a[x],然后把这个点入队
- 注意维护左右相邻的点
代码:
#include <cstdio> #include <algorithm> #include <iostream> #include <queue> #include <cstring> #include <algorithm> using namespace std; typedef long long LL; #define res register int inline LL read() { LL x=0,f=1;char ch; while(!isdigit(ch=getchar())) if(ch=='-') f=-1; while(isdigit(ch)) x=x*10+ch-'0',ch=getchar(); return f*x; } const int N=500000+10; struct node{ LL val,id; bool operator<(const node &n2) const { return val<n2.val; } }; int l[N],r[N],a[N]; bool inv[N]; int n,k; priority_queue<node> q; node t; int main() { n=read(); k=read(); for(res i=1 ; i<=n ; ++i) { a[i]=t.val=read(); t.id=i; l[i]=i-1; r[i]=i+1; q.push(t); } LL ans=0; while(k--) { while(inv[q.top().id]) q.pop(); t=q.top(); q.pop(); int num=t.id; if(t.val<0) break; ans+=t.val; t.val = a[num] = a[l[num]]+a[r[num]]-a[num]; inv[l[num]]=inv[r[num]]=1; l[num]=l[l[num]]; r[num]=r[r[num]]; r[l[num]]=num; l[r[num]]=num; q.push(t); } cout<<ans<<endl; return 0; }