luogu1484 种树 (优先队列)

我每次都想选那个最大的、或者是它旁边的两个一起选,如果这两个一起选会大于那个最大的的话

那我就先把那个最大的选了,再提供一个反悔的选项(类似于网络流的思路?),就是我可以再把种的树换成它旁边那两个,也是相当于又多种了一个,这个的权值是v[l]+v[r]-v[x]

所以用一个双向链表维护这个l、r,用一个优先队列维护这个最大值就好了

 1 #include<bits/stdc++.h>
 2 #define pa pair<ll,int>
 3 #define CLR(a,x) memset(a,x,sizeof(a))
 4 using namespace std;
 5 typedef long long ll;
 6 const int maxn=5e5+10;
 7 
 8 inline ll rd(){
 9     ll x=0;char c=getchar();int neg=1;
10     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
11     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
12     return x*neg;
13 }
14 
15 priority_queue<pa> q;
16 int N,K,nxt[maxn],pre[maxn];
17 ll v[maxn];
18 bool flag[maxn];
19 
20 int main(){
21     //freopen("","r",stdin);
22     int i;
23     N=rd(),K=rd();
24     for(i=1;i<=N;i++)
25         v[i]=rd(),q.push(make_pair(v[i],i));
26     for(i=1;i<=N;i++)
27         nxt[i]=i+1,pre[i]=i-1;
28     nxt[0]=1,pre[N+1]=N;
29     ll ans=0;
30     while(K&&!q.empty()){
31         pa p=q.top();q.pop();
32         int i=p.second,a=pre[i],b=nxt[i];
33         if(flag[i]) continue;
34         if(p.first<=0) break;
35         ans+=p.first;K--;
36         flag[a]=flag[b]=1;
37         v[i]=v[a]+v[b]-p.first;
38         pre[i]=pre[a],nxt[pre[a]]=i;
39         nxt[i]=nxt[b],pre[nxt[b]]=i;
40         q.push(make_pair(v[i],i));
41     }
42     printf("%lld\n",ans);
43     return 0;
44 }

猜你喜欢

转载自www.cnblogs.com/Ressed/p/9887264.html