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 }