并查集+multiset+双指针——cf982D
感觉自己的解法很复杂,写了一大堆代码
但核心是从小到大枚举每个元素的值,然后把<=当前元素的值进行合并,由于这个过程是单调的,所以可以直接将新的元素合并到旧的并查集里去
维护并查集的同时维护每个集合的大小size,将size放在multiset 里然后判断每个块的大小是否相同,如果相同则更新答案
#include<bits/stdc++.h> #include<set> using namespace std; #define maxn 200005 int a[maxn],n; struct Node {int pos,v;}p[maxn]; set<int>pq; set<int>::iterator itt; multiset<int>s; multiset<int>::iterator it; int cmp(Node a,Node b){return a.v<b.v;} int f[maxn],size[maxn],vis[maxn]; int find(int x){return f[x]==x?x:f[x]=find(f[x]);} void bing(int x,int y){ x=find(x);y=find(y); if(x==y)return; s.erase(s.find(size[x])); s.erase(s.find(size[y])); f[x]=y;size[y]+=size[x]; s.insert(size[y]); } int main(){ cin>>n; for(int i=1;i<=n;i++)cin>>a[i]; for(int i=1;i<=n;i++){ pq.insert(a[i]); p[i].pos=i;p[i].v=a[i]; } sort(p+1,p+1+n,cmp); for(int i=1;i<=n;i++)f[i]=i,size[i]=1; int Max=-1,ans,i=1; while(pq.size()){ itt=pq.begin(); int cur=*itt;pq.erase(itt); while(i<=n && p[i].v<=cur){//把<=cur的所有值都合并在一起 int pos=p[i].pos; s.insert(1);vis[pos]=1; if(pos>1 && a[pos-1]<=a[pos] && vis[pos-1]) bing(pos-1,pos); if(pos<n && a[pos+1]<=a[pos] && vis[pos+1]) bing(pos+1,pos); ++i; } int fir,end; it=s.begin();fir=*it; it=s.end();it--;end=*it; if(fir==end){ if((double)Max<(double)s.size()) Max=s.size(),ans=cur+1; } } cout<<ans<<endl; }