题目:

给定序列(a1,a2,⋅⋅⋅,an)=(1,2,⋅⋅⋅,n),即 ai=i。

小蓝将对这个序列进行 m 次操作,每次可能是将 a1,a2,⋯,aqi 降序排列,或者将aqi,aqi+1,⋯,an 升序排列。

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

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

接下来 m 行描述对序列的操作,其中第 i 行包含两个整数pi,qi 表示操作类型和参数。当pi=0 时,表示将 a1,a2,⋅⋅⋅,aqi 降序排列;当pi=1 时,表示将 aqi,aqi+1,⋯,an 升序排列。

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

输入输出样例
示例

输入

3 3
0 3
1 2
0 2

输出

3 1 2

样例说明
原数列为 (1, 2, 3)(1,2,3)。

第 11 步后为 (3, 2, 1)(3,2,1)。

第 22 步后为 (3, 1, 2)(3,1,2)。

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

评测用例规模与约定
对于 30%30% 的评测用例,n, m \leq 1000n,m≤1000;

对于 60%60% 的评测用例,n, m \leq 5000n,m≤5000;

对于所有评测用例,1 \leq n, m \leq 100000,0 \leq p_i \leq 1,1 \leq q_i \leq n1≤n,m≤100000,0≤pi≤1,1≤qi≤n。

运行限制
语言 最大运行时间 最大运行内存
C++ 1s 256M
C 1s 256M
Java 1s 256M
Python3 1s 256M

思路:

首先我想到的是根据条件进行暴力排序但只能通过40%的用例,然后就查看题解进行优化。

优化的思路就是将排序的次数进行压缩。以1 2 3 4 5 6 7 8 9为例

1.因为给定的数组一开始就是按照升序排列所以第一次排序一定是降序排列所以在找到第一次降序排列时所有的升序排列都不进行记数。

2.连续的降序排列我们只需要取范围最大的那一个如

4 3 2 1 5 6 7 8 9 1到4降序

6 5 4 3 2 1 7 8 9 1到6 降序

6 5 4 3 2 1 7 8 9 1到3降序

其中我们只用进行一次1到6降序即可其它两个降序排列可以省去。

3.连续的升序排列也是同理。最后会得到一个升序降序交替进行的结果。

代码:

import java.util.Scanner;

public class Main {
static int N = 100010;
static pair[] stk = new pair[N];
static int[] ans = new int[N];

public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int m = scanner.nextInt();
int top = 0;//初始化栈顶
int p, q;
for (int i = 0; i < m; i++) {
p = scanner.nextInt();
q = scanner.nextInt();
if (p == 0) {
//求出连续操作的最长前缀
while (top != 0 && stk[top].x == 0)
q = Math.max(q, stk[top--].y);
//删去所有比它小的前缀操作
while (top >= 2 && stk[top - 1].y <= q)
top -= 2;
//加上当前的前缀操作
stk[++top] = new pair(0, q);
} else if (top != 0) {

while (top != 0 && stk[top].x == 1)
q = Math.min(q, stk[top--].y);

while (top >= 2 && stk[top - 1].y >= q)
top -= 2;

stk[++top] = new pair(1, q);
}
} //这一部分是进行压缩,下面是进行排序。

int k = n, l = 1, r = n;

for (int i = 1; i <= top; i++) {
if (stk[i].x == 0) {

while (r > stk[i].y && l <= r) ans[r--] = k--;
} else {

while (l < stk[i].y && l <= r) ans[l++] = k--;
}
if (l > r) break;
}

if (top % 2 == 1) {
while (l <= r) ans[l++] = k--;
} else {
while (l <= r) ans[r--] = k--;
}
for (int i = 1; i <= n; i++) {
System.out.printf("%d ", ans[i]);
}
}

static class pair {
int x, y;

pair(int x, int y) {
this.x = x;
this.y = y;
}
}
}