并查集+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的主要内容,如果未能解决你的问题,请参考以下文章
CF576E Painting Edges [线段树分治,可撤销并查集]