luogu 1484\1792 种树 奇怪的贪心可反悔
1484 种树 此版本是线性的,那么根据链表维护即可;
构建新点,点的左右分别是原整个区间的前驱及后继,再正常维护即可
注意两个版本的维护有所不同
第二个版本的维护直接将左右两点删除
1792 种树2 此版本是环
1484
#include<bits/stdc++.h> #define ll long long using namespace std; const int N=500010; struct node{ ll v;int id; bool operator <(node a)const{ return v<a.v;}}; inline ll read(){ ll x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f;} ll a[N],ans; int l[N],r[N],vis[N]; priority_queue<node> q; int n,k; int main(){ n=read();k=read(); for(int i=1;i<=n;i++){ a[i]=read(); q.push((node){a[i],i}); l[i]=i-1;r[i]=i+1; }int len=n; for(int i=1;i<=k;i++){ while(!q.empty()&&vis[q.top().id]) q.pop(); if(q.empty()||q.top().v<0) break; node u=q.top();q.pop(); ans+=u.v; vis[u.id]=vis[l[u.id]]=vis[r[u.id]]=1; a[++len]=a[l[u.id]]+a[r[u.id]]-a[u.id]; l[len]=l[l[u.id]],r[len]=r[r[u.id]]; r[l[len]]=len;l[r[len]]=len; q.push((node){a[len],len}); }printf("%lld\n",ans); return 0; }
1792
#include<bits/stdc++.h> #define M 200050 #define rep(i,x,y) for(register int i=x;i<=y;i++) using namespace std; inline int read(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f;} struct node{ int v,id; friend bool operator < (node x,node y){ return x.v < y.v;} };priority_queue<node> q; int n,m,ans,chose,r[M],l[M],a[M]; bool vis[M]; void change(int x){ vis[x]=1; r[l[x]]=r[x]; l[r[x]]=l[x]; r[x]=0;l[x]=0;} int main(){ n=read(),m=read(); rep(i,1,n) a[i]=read(); if((n>>1)<m){ printf("Error!\n");return 0;} rep(i,1,n-1) r[i]=i+1;r[n]=1; rep(i,2,n) l[i]=i-1;l[1]=n; rep(i,1,n) q.push((node){a[i],i}); rep(i,1,m){ while(vis[q.top().id]) q.pop() ; node u=q.top();q.pop(); ans+=u.v; int ll=l[u.id],rr=r[u.id]; a[u.id]=a[ll]+a[rr]-a[u.id]; change(ll);change(rr); q.push((node){a[u.id],u.id}); }printf("%d\n",ans);return 0; }