并查集+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;
} 

 

posted on 2019-07-12 12:28  zsben  阅读(225)  评论(0编辑  收藏  举报

导航