洛谷1484 种树
【題意】給出一個n個數的序列,要求取出互補相鄰的m個數,使得它們的和最大。
【算法】貪心,堆
【題解】
每次取出最大的a,并且把a[i]設為a[pre[i]]+a[nxt[i]]-a[i]
這種做法類似于給貪心一個反悔的機會,這個反悔的機會實質上是擴大你選擇數字的影響范圍,一旦擴大就一定不會反悔,因為一定是最優的。
每次選擇一個數字相當于把原問題縮小范圍,改成在n-1個數中選出m-1個數
1 #include<cstdio> 2 #include<algorithm> 3 #include<queue> 4 #define LL long long 5 using namespace std; 6 const int maxn=1000010; 7 LL pre[maxn],nxt[maxn],a[maxn],n,m,x,ans=0; 8 bool mark[maxn]; 9 priority_queue<pair<LL,LL>,vector<pair<LL,LL> > >q; 10 inline int read(){ 11 int k=0,f=1; char c=getchar(); 12 while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); 13 while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar(); 14 return k*f; 15 } 16 void del(int x){ 17 mark[x]=1; 18 pre[nxt[x]]=pre[x]; nxt[pre[x]]=nxt[x]; 19 pre[x]=nxt[x]=0; 20 } 21 int main(){ 22 n=read(); m=read(); 23 for(int i=1;i<=n;i++) a[i]=read(),q.push(make_pair(a[i],i)); 24 if(m>n/2){puts("ERROR"); return 0;} 25 for(int i=1;i<=n;i++) pre[i]=i-1,nxt[i]=i+1; //pre[1]=n; nxt[n]=1; 26 for(int i=1;i<=m;i++){ 27 while(mark[q.top().second]) q.pop(); 28 int tmp=q.top().second; q.pop(); 29 if(a[tmp]<0) break; 30 ans+=a[tmp]; 31 a[tmp]=a[pre[tmp]]+a[nxt[tmp]]-a[tmp]; q.push(make_pair(a[tmp],tmp)); 32 del(pre[tmp]); del(nxt[tmp]); 33 } 34 return printf("%lld\n",ans),0; 35 } View Code?
轉載于:https://www.cnblogs.com/DriverLao/p/8035149.html
總結
- 上一篇: jQuery——stop
- 下一篇: 《软件过程改进》练习题