题纲
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;
}