3419. 双向排序

题目链接

3419. 双向排序

给定序列 \((a_1,a_2,⋅⋅⋅,a_n)=(1,2,⋅⋅⋅,n)\),即 \(a_i=i\)

小蓝将对这个序列进行 \(m\) 次操作,每次可能是将 \(a_1,a_2,⋅⋅⋅,a_{q_i}\) 降序排列,或者将 \(a_{q_i},a_{q_{i+1}},⋅⋅⋅,a_n\) 升序排列。

请求出操作完成后的序列。

输入格式

输入的第一行包含两个整数 \(n,m\),分别表示序列的长度和操作次数。

接下来 \(m\) 行描述对序列的操作,其中第 \(i\) 行包含两个整数 \(p_i,q_i\) 表示操作类型和参数。当 \(p_i=0\) 时,表示将 \(a_1,a_2,⋅⋅⋅,a_{q_i}\) 降序排列;当 \(p_i=1\) 时,表示将 \(a_{q_i},a_{q_{i+1}},⋅⋅⋅,a_n\) 升序排列。

输出格式

输出一行,包含 \(n\) 个整数,相邻的整数之间使用一个空格分隔,表示操作完成后的序列。

数据范围

对于 \(30\%\) 的评测用例,\(n,m≤1000\)
对于 \(60\%\) 的评测用例,\(n,m≤5000\)
对于所有评测用例,\(1≤n,m≤10^5,0≤p_i≤1,1≤q_i≤n\)

输入样例:

3 3
0 3
1 2
0 2

输出样例:

3 1 2

样例解释

原数列为 \((1,2,3)\)

\(1\) 步后为 \((3,2,1)\)

\(2\) 步后为 \((3,1,2)\)

\(3\) 步后为 \((3,1,2)\)。与第 \(2\)步操作后相同,因为前两个数已经是降序了。

解题思路

思维

首先可以肯定的一点:前缀操作和后缀操作是交替进行的,且第一步操作肯定是前缀操作,因为如果出现连续的前缀操作或者后缀操作,这些连续的操作都可以合成一个操作
另外以前缀操作为例:如果一个前缀操作可以覆盖上一个前缀操作,由于这个操作包含的元素包括了前两次的元素,所以这次前缀操作可以取代前两次操作,后缀操作也是如此

  • 时间复杂度:\(O(n+m)\)

代码

// Problem: 双向排序
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/3422/
// Memory Limit: 256 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

const int N=1e5+5;
PII stk[N];
int top,res[N];
int main()
{
    int n,m;
    cin>>n>>m;
    while(m--)
    {
    	int p,q;
    	cin>>p>>q;
    	if(p==0)
    	{
    		while(top&&stk[top].fi==0)q=max(stk[top--].se,q);
    		while(top>=2&&stk[top-1].se<q)top-=2;
    		stk[++top]={0,q};
    	}
    	else if(top)
    	{
    		while(top&&stk[top].fi==1)q=min(stk[top--].se,q);
    		while(top>=2&&stk[top-1].se>q)top-=2;
    		stk[++top]={1,q};
    	}
    }
    int l=1,r=n,k=n;
	for(int i=1;i<=top;i++)
	{
		if(stk[i].fi==0)
			while(l<=r&&stk[i].se<r)res[r--]=k--;
		else
			while(l<=r&&stk[i].se>l)res[l++]=k--;
		if(l>r)break;
	}
	if(top&1)
		while(l<=r)res[l++]=k--;
	else
		while(l<=r)res[r--]=k--;
	for(int i=1;i<=n;i++)cout<<res[i]<<' ';
    return 0;
}
posted @ 2022-02-20 23:23  zyy2001  阅读(311)  评论(0编辑  收藏  举报