题目大意

有n个数,依次加进栈中,每次加入前将栈顶比大的所有元素弹掉,加入后记为栈的大小

现在给你b中的一些数,让你求a数组的一种合法方案,其中1~n在a中各出现了一次


解题思路

每次把栈顶比大的所有元素弹掉,使得栈是单调递增的

对于所求a数组,可以先连边,表示该点要比哪个点大,然后跑拓扑序

那么可以遍历每个b,如果当前栈中剩余的数大于了个,那么把这些数弹掉,且弹掉的数中最小的数连向i(这些数要比大才能被弹掉),把i加进栈中,然后连向栈顶(栈顶不会被弹掉)

最后跑拓扑序编号


代码

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define N 1000100
using namespace std;
int n, m, x, w, p, g, res, st[N], v[N], b[N], to[N], deg[N];
queue<int>d;
void bfs()
{
    for (int i = 1; i <= n; ++i)
        if (!deg[i]) d.push(i);
    w = n;
    while(!d.empty())
    {
        int u = d.front();
        d.pop();
        v[u] = w--;
        if (!--deg[to[u]]) d.push(to[u]);
    }
    return;
}
int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= m; ++i)
    {
        scanf("%d", &x);
        scanf("%d", &b[x]);
    }
    res = 0;
    for (int i = 1; i <= n; ++i)
    {
        if (b[i])
        {
            if (b[i] > res + 1)//所要求的比当前剩余的大,所以不可能
            {
                p = 1;
                break;
            }
            g = 0;
            while(b[i] < res + 1)//多了
                res--, g = 1;
            if (g) to[st[res + 1]] = i;//最低的点比大
        }
        st[++res] = i; //入栈
        to[st[res]] = st[res - 1];//i比栈顶大
    }
    if (p == 1)
    {
        puts("-1");
        return 0;
    }
    for (int i = 1; i <= n; ++i)
        deg[to[i]]++;
    bfs();//跑拓扑序
    for (int i = 1; i <= n; ++i)
        printf("%d ", v[i]);
    return 0;
}