2021牛客暑期多校训练营10 F.Train Wreck(栈,并查集,优先队列,贪心)
Posted issue是fw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021牛客暑期多校训练营10 F.Train Wreck(栈,并查集,优先队列,贪心)相关的知识,希望对你有一定的参考价值。
题意
有 n n n个元素,第 i i i个元素的颜色为 c o l o r i color_i colori
给定一个长度为 2 ∗ n 2*n 2∗n的进出栈括号序列(每个元素恰好进栈一次出栈一次)
要求你构造长度为 n n n的序列 a n s ans ans,其中 a n s i ans_i ansi表示第 i i i次入栈的元素颜色
满足每次刚加入 a n s i ans_i ansi后栈中形成的颜色序列抽出来(显然有 n n n个颜色序列)
这 n n n个颜色序列是各不相同的
对这个进出栈的括号序列进行模拟
记录最后一次退栈时退出的元素是 x 1 x_1 x1
那么当下次如果是让元素 x 2 x_2 x2入栈,必须满足 x 1 x_1 x1和 x 2 x_2 x2的颜色不同
因为这两个序列的前缀都是相同的了
这样一来,现在的前缀已经不同,所以下次入栈就没有限制,我们令 x 1 = 0 x_1=0 x1=0
但一旦出现退栈,我们又需要记录 x 1 x_1 x1,这样反复做
我们可以得到哪些元素的颜色需要互不相同,做一个并查集即可
于是现在得到了 k k k个集合,第 i i i个集合内有 s i z i siz_i sizi个元素,需要满足集合内的颜色互不相同
这就是一个经典的贪心,我们按照每种颜色多少排个序,倒序枚举
设第 j j j中颜色有 z z z个,我们给当前前 z z z大的集合都分配一个颜色 j j j…
按照这样一直做,集合的动态大小使用优先队列维护即可
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+10;
int n,top,fa[maxn],shu[maxn],nor[maxn],ind[maxn],sta[maxn];
char a[maxn<<1];
int find(int x){ return x==fa[x]?x:fa[x]=find( fa[x] );}
void join(int q,int w){ fa[find(q)]=find(w); }
priority_queue<pair<int,int> >q,color;
void OVER()
{
cout << "NO";
exit( 0 );
}
vector<int>ans[maxn];
int main()
{
ios::sync_with_stdio( false );
cin >> n >> ( a+1 );
for(int i=1;i<=n;i++)
{
int col; cin >> col;
shu[col]++;
}
for(int i=1;i<=n;i++)
if( shu[i] ) color.push( {shu[i],i} );
for(int i=1;i<=n;i++) fa[i] = i;
int id = 0, las = 0;
for(int i=1;i<=2*n;i++)
{
if( a[i]=='(' )
{
sta[++top] = ++id;
if( las ) join( las,id ), las = 0;
}
else las = sta[top--];
}
for(int i=1;i<=n;i++) fa[i] = find( fa[i] );
for(int i=1;i<=n;i++) nor[ fa[i] ]++;
for(int i=1;i<=n;i++)
if( nor[i] ) q.push( { nor[i],i } );
while( !color.empty() )
{
int cap = color.top().first, type = color.top().second;
color.pop();
vector<pair<int,int> >vec;
for(int i=1;i<=cap;i++)
{
if( q.empty() ) OVER();
int fi = q.top().first, se = q.top().second;
ans[se].push_back( type );
q.pop();
if( fi>1 )
vec.push_back( {fi-1,se} );
}
for(auto v:vec ) q.push( v );
}
cout << "YES\\n";
for(int i=1;i<=n;i++)
cout << ans[fa[i]][ind[fa[i]]++] << " ";
}
以上是关于2021牛客暑期多校训练营10 F.Train Wreck(栈,并查集,优先队列,贪心)的主要内容,如果未能解决你的问题,请参考以下文章