2021牛客多校2 - Stack(单调栈+拓扑)

Posted Frozen_Guardian

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021牛客多校2 - Stack(单调栈+拓扑)相关的知识,希望对你有一定的参考价值。

题目链接:点击查看

题目大意:给出 b [ i ] b[i] b[i] 数组的求解过程:

Stk is an empty stack
for i = 1 to n :
    while ( Stk is not empty ) and ( Stk's top > a[i] ) : 
        pop Stk
    push a[i]
    b[i]=Stk's size

现在给出 b b b 数组的 k k k 个位置,要求构造出一组合法的数组 a a a 作为答案

题目分析:任意解感觉没有什么可扩展性,所以这里主要记录一下字典序最小的合法解该如何构造

首先特判无解的情况,对于某个位置 b [ i ] b[i] b[i] 来说,如果没有给出具体数值,那么贪心去想,令其为 b [ i ] = b [ i − 1 ] + 1 b[i]=b[i-1]+1 b[i]=b[i1]+1 一定是最优的,如果此时仍然碰到了 b [ i ] − b [ i − 1 ] > 1 b[i]-b[i-1]>1 b[i]b[i1]>1 的情况,那只能说明无解了

接下来一定是有解的情况,我们用单调栈维护下标去模拟整个过程,如果 b [ i ] < = b [ i − 1 ] b[i]<=b[i-1] b[i]<=b[i1] 的话,说明我们需要将单调栈进行弹出操作,既然需要用 a [ i ] a[i] a[i] 去弹出,设被弹出的位置为 x x x,那么显然不等式 a [ i ] < a [ x ] a[i]<a[x] a[i]<a[x] 成立。最后需要让 i i i 入栈,此时肯定有 a [ i ] > a [ t o p ] a[i]>a[top] a[i]>a[top] 成立,同时这里也涵盖了 b [ i ] > b [ i − 1 ] b[i]>b[i-1] b[i]>b[i1],即 b [ i ] = b [ i − 1 ] + 1 b[i]=b[i-1]+1 b[i]=b[i1]+1 的情况,所以讨论完毕

知晓了相对大小关系后,建图跑一遍拓扑就可以获得答案了,因为每个点 i i i 只会入栈、出栈各一次,所以边至多有 2 ∗ n 2*n 2n

并且贪心去赋值的话,这样求出来的答案一定是字典序最小的一种合法解

代码:

// Problem: Stack
// Contest: NowCoder
// URL: https://ac.nowcoder.com/acm/contest/11253/K
// Memory Limit: 524288 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// #pragma GCC optimize(2)
// #pragma GCC optimize("Ofast","inline","-ffast-math")
// #pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
#include<list>
#include<unordered_map>
#define lowbit(x) (x&-x)
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
template<typename T>
inline void read(T &x)
{
	T f=1;x=0;
	char ch=getchar();
	while(0==isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(0!=isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
	x*=f;
}
template<typename T>
inline void write(T x)
{
	if(x<0){x=~(x-1);putchar('-');}
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
const int inf=0x3f3f3f3f;
const int N=1e6+100;
int ans[N],b[N],in[N],n;
vector<int>node[N];
void addedge(int u,int v) {
	node[u].push_back(v);
	in[v]++;
}
void topo() {
	queue<int>q;
	int tot=0;
	for(int i=1;i<=n;i++) {
		if(!in[i]) {
			q.push(i);
		}
	}
	while(q.size()) {
		int u=q.front();
		q.pop();
		ans[u]=++tot;
		for(auto v:node[u]) {
			if(--in[v]==0) {
				q.push(v);
			}
		}
	}
}
int main()
{
#ifndef ONLINE_JUDGE
//	freopen("data.in.txt","r",stdin);
//	freopen("data.out.txt","w",stdout);
#endif
//	ios::sync_with_stdio(false);
	int k;
	read(n),read(k);
	for(int i=1;i<=k;i++) {
		int x;
		read(x);
		read(b[x]);
	}
	for(int i=1;i<=n;i++) {
		if(!b[i]) {
			b[i]=b[i-1]+1;
		} else if(b[i]-b[i-1]>1) {
			return 0*puts("-1");
		}
	}
	stack<int>st;
	for(int i=1;i<=n;i++) {
		//b[i-1]>=b[i]:a[i]<st[b[i]]
		while((int)st.size()>=b[i]) {
			addedge(i,st.top());
			st.pop();
		}
		if(st.size()) {
			addedge(st.top(),i);
		}
		st.push(i);
	}
	topo();
	for(int i=1;i<=n;i++) {
		printf("%d ",ans[i]);
	}
	return 0;
}

以上是关于2021牛客多校2 - Stack(单调栈+拓扑)的主要内容,如果未能解决你的问题,请参考以下文章

2021牛客暑期多校训练营2 K.Stack(构造,拓扑排序)

Move (牛客多校) (诈骗二分,诈骗复杂度)

2021牛客多校2 C Draw Grids

2021牛客多校2 D Er Ba Game

2021牛客多校8 D OR

2021牛客多校8 D.OR(位运算)