1101 Quick Sort (25分)

开始觉得是个什么两次遍历法,后来发现是RMQ问题,可以选择线段树,树状数组,ST表三种
再看数据范围:(N <= 10^5)
线段树/树状数组:(O(nlogn))
ST表:(O(n))

#include<iostream>
#include<cmath>
#include<vector>
#include<algorithm>

using namespace std;

const int N = 100010;

int a[N];
int maxv[N][20], minv[N][20];
int n;
vector<int> res;

void init(){
    int k = log(n) / log(2);
    
    for(int i = 1; i <= n; i ++) maxv[i][0] = a[i];
    for(int i = 1; i <= n; i ++) minv[i][0] = a[i];
    
    for(int j = 1; j <= k; j ++)
        for(int i = 1; i + (1 << j) - 1 <= n; i ++){
            maxv[i][j] = max(maxv[i][j - 1], maxv[i + (1 << j - 1)][j - 1]);
            minv[i][j] = min(minv[i][j - 1], minv[i + (1 << j - 1)][j - 1]);
        }
}

int query_max(int l, int r){
    if(r < l) return -1;
    int k = log(r - l + 1) / log(2);
    return max(maxv[l][k], maxv[r - (1 << k) + 1][k]);
}

int query_min(int l, int r){
    if(r < l) return 0x3f3f3f3f;
    int k = log(r - l + 1) / log(2);
    return min(minv[l][k], minv[r - (1 << k) + 1][k]);
}

int main(){
    cin >> n;
    
    for(int i = 1; i <= n; i ++) cin >> a[i];
    
    init();
    
    for(int i = 1; i <= n; i ++){
        int l = query_max(1, i - 1), r = query_min(i + 1, n);
        // cout << l << ' ' << r << endl;
        if(l < a[i] && r > a[i]) res.push_back(a[i]);
    }
    
    sort(res.begin(), res.end());
    
    cout << res.size() << endl;
    
    if(res.size()){
        cout << res[0];
        for(int i = 1; i < res.size(); i ++) cout << ' ' << res[i]; 
    }else puts("");
    
    return 0;
}

两次遍历法:(O(n))

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

const int N = 100010;

int minv[N], maxv[N];
int n;
int a[N];
vector<int> res;

int main(){
    cin >> n;
    
    for(int i = 1; i <= n; i ++) cin >> a[i];
    
    maxv[1] = -1;
    minv[n] = 0x3f3f3f3f;
    for(int i = 2; i <= n; i ++) maxv[i] = max(maxv[i - 1], a[i - 1]);
    for(int i = n - 1; i >= 1; i --) minv[i] = min(minv[i + 1], a[i + 1]);
    
    for(int i = 1; i <= n; i ++)
        if(maxv[i] < a[i] && minv[i] > a[i]) res.push_back(a[i]);
        
    sort(res.begin(), res.end());
    
    cout << res.size() << endl;
    
    if(res.size()){
        cout << res[0];
        for(int i = 1; i < res.size(); i ++) cout << ' ' << res[i];
    }else puts("");
    
    return 0;
}
原文地址:https://www.cnblogs.com/tomori/p/13757362.html