zoukankan      html  css  js  c++  java
  • bzoj 2151 种树——贪心+后悔

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2151

    似乎是半年+前讲过的。(然而看到的时候却不会了)

    考虑贪心,限制就是不能选两边的。如果选了最大的又要反悔,一定不可能是要只选旁边的一个,而是把两个都选了;

    所以选了这个以后,把两边的打上标记表示不能选,往堆里加入一个值为 两边的值-自己的值 的元素表示反悔选择即可。

    维护两边是谁,自己用了链表。也许这就是自己很慢的原因?

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const int N=2e5+5;
    int n,m,a[N<<1],tot,ans,pr[N<<1],nt[N<<1];
    bool vis[N<<1];
    struct cmp{
      bool operator() (int u,int v)
      {
        return a[u]<a[v];
      }
    };
    priority_queue<int,vector<int>,cmp> q;
    int rdn()
    {
      int ret=0;bool fx=1;char ch=getchar();
      while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
      while(ch>='0'&&ch<='9') ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
      return fx?ret:-ret;
    }
    int main()
    {
      n=rdn(); m=rdn(); tot=n;
      for(int i=1;i<=n;i++)
        {
          a[i]=rdn();q.push(i);
          pr[i]=i-1;nt[i]=i+1;
        }
      if(m>(n>>1)){puts("Error!");return 0;}
      pr[1]=n; nt[n]=1;
      for(int i=1,x,y,k;i<=m;i++)
        {
          k=q.top(); q.pop();
          while(vis[k])k=q.top(),q.pop();
          ans+=a[k]; x=pr[k]; y=nt[k];
          a[++tot]=a[x]+a[y]-a[k]; q.push(tot);
          vis[x]=1; vis[y]=1;
          nt[pr[x]]=tot; pr[tot]=pr[x];
          pr[nt[y]]=tot; nt[tot]=nt[y];
        }
      printf("%d
    ",ans);
      return 0;
    }
  • 相关阅读:
    进程与线程
    Socket函数编程(二)
    socket编程
    subprocess 模块
    异常处理
    模块与包
    【Java基础】String源码分析
    【MySQL】 执行计划详解
    【MySQL】performance schema详解
    【Spring Cloud-Open Feign】使用OpenFeign完成声明式服务调用
  • 原文地址:https://www.cnblogs.com/Narh/p/9817886.html
Copyright © 2011-2022 走看看