CF 631C

题目:

对n<200000的数组,给出m种从1开始到r为止的升序或降序排序,m<200000,求最终输出序列

题解:

1. 不管前面排了多少次小区间,只要在后面排了一次大区间,结果只受最后一次排序影响。所以维护单调队列。

2. 前面是大区间,后面是小区间,只有当排序方式不同时才需要重新排序。

3. 第一次排序过后剩下的排序等价于翻转。

好这样就有了O(N2)的算法,暴力一波看看数据水不水。


……那再优化一下……

翻转不需要真的翻转,每一次更小区间的翻转都会空出最右端的数字,这个数字满足前一次排序的性质。

所以我们还得维护一个表示所需数字的单调队列。

还有一些小细节,自行注意。

#include
#include
#include
#include
using namespace std;

struct S{
    int t,r;
}s[201000];

int arr[201000];
int ans[201000];
deque deq;//单调递减队列
deque smooth;//单调递增队列

int main(){
    int n,m;
    cin>>n>>m;
    for(int i=0;i>arr[i];
    }
    for(int i=0;i>s[i].t>>s[i].r;
    }
    for(int i=0;i=deq.back().r){
            deq.pop_back();
        }
        deq.push_back(s[i]);
    }
    S now=deq.front();
    sort(arr,arr+now.r);
    for(int i=0;i());
    else sort(arr,arr+now.r,greater());
    deq.pop_front();
    for(int i=now.r;i=nex;i--){
                ans[i]=smooth.back();
                smooth.pop_back();
            }
        }
        else{
            for(int i=now.r-1;i>=nex;i--){
                ans[i]=smooth.front();
                smooth.pop_front();
            }
        }
    }
    for(int i=0;i

你可能感兴趣的:(数据结构)