并查集+multiset+双指针——cf982D

Posted zsben991126

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了并查集+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;
 

 

以上是关于并查集+multiset+双指针——cf982D的主要内容,如果未能解决你的问题,请参考以下文章

并查集CF731CSocks

CF576E Painting Edges [线段树分治,可撤销并查集]

CF576E Painting Edges [线段树分治,可撤销并查集]

CF 891C Envy 最小生成树+可撤销并查集

CF553C Love Triangles(带权并查集)

cf-Round541-Div2-F(并查集+静态链表)