hihocoder 1356 分隔相同整数 简单贪心

分析:考虑贪心,考虑填ans[i],前i-1个合法,现在剩下一些数,

        那么挑出出现次数最多的数,次数为mx,当前剩余总数为sum

        如果sum-mx>=mx-1那么肯定有解,这个想想就知道了(这种题做过无数遍了)

        考虑当前填的数,如果sum-mx=mx-1,那么只能填出现次数最多的数

        否则,贪心选择和ans[i-1]不一样且最小的,因为求字典序,所以每次贪心是对的

#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <set>
#include <queue>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 1e5+5;
const int INF = 0x3f3f3f3f;
typedef pair<int,int>pii;
int a[N],n,p[N],c[N],tot;
set<pii>s;
set<pii>::iterator it;
int main(){
  scanf("%d",&n);
  for(int i=1;i<=n;++i)
    scanf("%d",&a[i]);
  sort(a+1,a+1+n);
  for(int i=1;i<=n;++i){
    int cnt=1;
    while(i+1<=n&&a[i+1]==a[i])++i,++cnt;
    s.insert(make_pair(cnt,a[i]));
    ++tot;p[tot]=a[i];c[tot]=cnt;
  }
  int j=1;
  bool flag=0;
  for(int i=1;i<=n;++i){
    it=s.end();--it;
    int cur=n-i+1,mxcnt=it->first;
    if(cur-mxcnt<mxcnt-1){
        printf("-1
");
        return 0;
    }
    if(cur-mxcnt>mxcnt-1){
      while(j<=tot&&c[j]==0)++j;
      int k=j;
      for(;k<=tot;++k){
        if(c[k]&&p[k]!=a[i-1])break;
      }
      if(k==tot+1){
          printf("-1
");
         return 0;
      }
      pii tmp=make_pair(c[k],p[k]);
      s.erase(tmp);
      a[i]=p[k];
      --c[k];
      if(c[k]) s.insert(make_pair(c[k],p[k]));
    }
    else{
      a[i]=it->second;
      int pos=lower_bound(p+1,p+1+tot,a[i])-p;
      --c[pos];
      s.erase(it);
      if(c[pos])
        s.insert(make_pair(c[pos],p[pos]));  
    }
  } 
  for(int i=1;i<n;++i)printf("%d ",a[i]);
      printf("%d
",a[n]);
  return 0;
}
View Code
原文地址:https://www.cnblogs.com/shuguangzw/p/5746198.html