分析:考虑贪心,考虑填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; }