zoukankan      html  css  js  c++  java
  • 洛谷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
    ",ans),0;
    35 }
    View Code
  • 相关阅读:
    forceStopPackage与killBackgroundProcesses方法
    github上十二款最著名的Android播放器开源项目
    AndroidStudio编译错误:Error: null value in entry: blameLogFolder=null
    Vue相关开源项目库汇总 http://www.opendigg.com/tags/front-vue
    Android Drawable 那些不为人知的高效用法
    Android数据存储
    touch事件的分发机制
    Hybrid 开发
    关于Http协议
    设计原理+设计模式
  • 原文地址:https://www.cnblogs.com/DriverLao/p/8035149.html
Copyright © 2011-2022 走看看