2021牛客暑期多校训练营2 K.Stack(构造,拓扑排序)
Posted issue是fw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021牛客暑期多校训练营2 K.Stack(构造,拓扑排序)相关的知识,希望对你有一定的参考价值。
已知 b i b_i bi和 b j b_j bj,若 b i + ( j − i ) < b j b_i+(j-i)<b_j bi+(j−i)<bj肯定无解,因为每个元素都入栈仍无法满足存在 b j b_j bj个元素
所以可以发现,在相邻的 b i , b j b_i,b_j bi,bj之间的元素都加进去比较好
如果在 b j b_j bj处发现多了,可以构造一个 a j a_j aj弹出适量元素,但是少了就直接无解了.
于是为了方便,我们构造 b i + 1 = b i + 1 b_{i+1}=b_i+1 bi+1=bi+1
初始设一个栈,栈中存放的是没有被弹出去的 a a a元素下标
所以每次加入新元素 a i a_i ai时就把 i i i入栈
若此处 b i b_i bi没有限制,只需要让 i − 1 i-1 i−1向 i i i连一条边,表示 a i − 1 < a i a_{i-1}<a_i ai−1<ai
若此处 b i b_i bi有限制,检查一下栈中的元素是否大于 b i b_i bi
若小于说明无解,因为加入新元素只会弹栈
若大于等于有解,先计算出需要弹出 z z z个元素,此时栈顶元素为 s [ t o p ] s[top] s[top],最后一个被弹出栈的元素为 s [ t o p + 1 ] s[top+1] s[top+1]
说明 a i > a s [ t o p ] & & a i < a s [ t o p + 1 ] a_i>a_{s[top]}\\&\\&a_i<a_{s[top+1]} ai>as[top]&&ai<as[top+1]
然后由小的一方向大的一方连边即可
最后连完是个 D A G \\rm DAG DAG,跑一遍拓扑排序即可构造一组合法解
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+10;
int n,k,b[maxn],ans[maxn],in[maxn],s[maxn],top;
vector<int>vec[maxn];
void add(int l,int r){ vec[l].push_back( r ); in[r]++; }
void tuopu()
{
queue<int>q;
for(int i=1;i<=n;i++)
if( !in[i] ) q.push( i );
int siz = 0;
while( !q.empty() )
{
int u = q.front(); q.pop();
ans[u] = ++siz;
for(auto v:vec[u] )
if( --in[v]==0 ) q.push( v );
}
for(int i=1;i<=n;i++)
printf("%d%c",ans[i],i==n?'\\n':' ');
}
signed main()
{
cin >> n >> k;
for(int i=1;i<=k;i++)
{
int p,x; cin >> p >> x;
b[p] = x;
}
for(int i=1;i<=n;i++)
{
s[++top] = i;
if( b[i] && top<b[i] ) { cout << -1; return 0; }
if( i==1 ) continue;
if( b[i] && top>b[i] )//有限制,弹栈
{
top = b[i]-1;//s[top]小于i,而s[top+1]大于i
add( i,s[top+1] );
if( top ) add( s[top],i );
s[++top] = i;
}
else add( i-1,i );//i-1小于i
}
tuopu();
}
以上是关于2021牛客暑期多校训练营2 K.Stack(构造,拓扑排序)的主要内容,如果未能解决你的问题,请参考以下文章