试题 I:双向排序
暴力法
对于每一组操作,通过 sort
函数对原数组排序,但这样时间复杂度高,无法通过所有测试用例。
Idea
我们试着减少那些不必要的重复排序操作。通过分析可以得到以下结论:
-
第一次有意义的操作是降序操作(即
0
开头)数组一开始是按照升序排列的,所有最开始的升序操作没必要执行
-
对于升序操作(降序同理),当输入
(1 q)
时,只需对[q,n]
进行操作,前面的[1,q-1]
保持不变 -
连续的同类型操作合并为范围最大的那个
例如,连续两行输入
(0 2) (0 3)
,可以合并为(0 3)
-
每次同类型的操作都会合并,因此升序、降序操作在数组
stk
中交替出现(最开始的操作为降序) -
利用结论四,对于当前输入的升序操作(降序同理),可以很容易追溯上一次的升序操作,如果当前升序操作的操作范围更大,可以证明上一次的升序操作以及它之后的降序操作是无效的
-
通过性质三的合并操作与性质五的追溯操作,数组
stk
中存放的升序操作(降序同理)对应的操作范围随着下标的增加单调递减
之后我们要遍历数组 stk
中存放的操作,利用结论二与结论六,数组 stk
中的每个操作都可以使一部分的数不需要进行排序操作,这样可以很方便的确定这些数最终存放的位置。
#include <iostream>
using namespace std;
const int N = 100000;
pair<int, int> stk[N]; // 存放每一步进行的操作
int ans[N]; // 存放最终的结果
int main() {
int m, n, top = 0;
cin >> n >> m