题意:给你一个序列,让你找一个k,倘若把大于等于k的元素都标记为不可用,那么剩下的所有元素形成的段的长度相同,并且使得段的数量尽量大。如果有多解,输出k尽量小的。
把元素从大到小排序插回原位置,用一个set维护前驱后继,相当于删除一个原有的段,然后将这个段切成两半,产生两个新的段。维护这次操作后所有段的长度以及各种长度的出现次数(用multiset),一旦合法,就尝试更新答案。
#include<cstdio> #include<algorithm> #include<set> using namespace std; typedef pair<int,int> Point; set<int>S; multiset<int>S2; int n; Point a[100005]; int all,ans,maxnum; int main(){ scanf("%d",&n); int x; S2.insert(n); maxnum=1; for(int i=1;i<=n;++i){ scanf("%d",&x); a[i].first=x; a[i].second=i; } sort(a+1,a+n+1); ans=a[n].first+1; S.insert(0); S.insert(n+1); for(int i=n;i>=1;--i){ S.insert(a[i].second); int y=*S.upper_bound(a[i].second); set<int>::iterator it=S.lower_bound(a[i].second); --it; int x=*it; S2.erase(S2.find(y-x-1)); if(y-a[i].second>1){ S2.insert(y-a[i].second-1); } if(a[i].second-x>1){ S2.insert(a[i].second-x-1); } if(!S2.empty()){ multiset<int>::iterator jt=S2.end(); --jt; if((*S2.begin())==(*jt)){ if(S2.size()>maxnum || (S2.size()==maxnum && a[i-1].first+1<ans)){ maxnum=S2.size(); ans=a[i-1].first+1; } } } } printf("%d\n",ans); return 0; }
原文地址:https://www.cnblogs.com/autsky-jadek/p/9055525.html
时间: 2024-10-03 05:36:29