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;
}