题纲

Permutation Subsequence

来源:abc352 D

记数 \(i\) 在序列中的位置为 \(pos_i\)

容易发现这道题本质是求所有长度为 \(k\) 的区间 \([l,r]\)\(max(pos[l,r])-min(pos[l,r])\) 的最小值

暴力是简单的,枚举区间左端点,\(O(n)\) 遍历枚举到的区间,求答案,整体复杂度 \(O(n^2)\)

优化可以直接上权值线段树,可以做到 \(O(\log)\) 求区间最大值、最小值

但发现这是 abc 的题,打 abc 基本没打过线段树,所以考虑直接 st 表维护区间最大值最小值,复杂度瓶颈在预处理上 \(O(n\log)\)

code
#include<bits/stdc++.h>
#define Aqrfre(x, y) freopen(#x ".in", "r", stdin),freopen(#y ".out", "w", stdout)
#define mp make_pair
#define Type int
#define qr(x) x=read()
typedef long long ll;
using namespace std;

inline Type read(){
    char c=getchar(); Type x=0, f=1;
    while(!isdigit(c)) (c=='-'?f=-1:f=1), c=getchar();
    while(isdigit(c)) x=(x<<1)+(x<<3)+(c^48), c=getchar();
    return x*f;
}

const int N = 2e5 + 5; 

int n, k, p[N], pos[N];
int stmax[20][N], stmin[20][N];

inline int getmax(int l){
    int r = l + k - 1, lg2 = log2(k);
    return max(stmax[lg2][l], stmax[lg2][r-(1<<lg2)+1]);
}

inline int getmin(int l){
    int r = l + k - 1, lg2 = log2(k);
    return min(stmin[lg2][l], stmin[lg2][r-(1<<lg2)+1]);
}

signed main(){ // a
    // Aqrfre(a, a);

    qr(n); qr(k);
    for(int i=1; i<=n; i++) qr(p[i]), pos[p[i]] = i, stmax[0][p[i]] = stmin[0][p[i]] = i;
    for(int j=1; j<=18; j++){
        for(int i=1; i<=n; i++)
            stmax[j][i] = max(stmax[j-1][i], stmax[j-1][i+(1<<j-1)]),
            stmin[j][i] = min(stmin[j-1][i], stmin[j-1][i+(1<<j-1)]);
    }

    int ans = 2e9; 
    for(int l=1; l+k-1<=n; l++)
        ans = min(ans, getmax(l) - getmin(l));
    cout<<ans<<"\n";



    return 0;
}
posted @ 2024-11-07 21:01  Aqr_Rn  阅读(42)  评论(8编辑  收藏  举报