线段树 求 (RMQ)问题 (orz) 原因是因为我的(ST)表炸了
(我太弱了)
(RMQ)问题通常是求区间最值。 比如说 :(X - Y)的最大值?
这样的问题往往无从下手 我们需要一个解决(RMQ)问题的算法。
比如说是:(ST)表 , 线段树。
其实还有单调队列的方法。 其他题解也说到了。(代码简短)
可我还是不知道为什么我选了 (ST)表 && 线段树。
可能是因为我比较笨吧(大雾
先讲讲(ST)表吧 虽然说不能(AC) 但是我看见有人 用这个方法(AC) 了
(ST)表的思路主要是 预处理 然后 (O(1))复杂度的查询 适合这种问题
用一个(f[i][j]) 来 表示 (i) ~ $ i + 2^j(的最大值 从而到这样 这样子时间是完全)ojbk$的 但是反观 内存 (n log n)的一个内存 (N<=200w) 所以显然不行
(如果有哪位神仙用(ST)表AC了麻烦点评测记录告诉我如何不(MLE))
评测记录:(Here)
所以去想线段树 线段树的查询大概是(log n)
(n log n) 也勉强过得去吧。
但是貌似没有单调队列快(还不是我弱)
回归正题 线段树 (分治的方法
首先我们需要定义数组 以及 建树
const int N = 2e6 + 10 ;
struct node {
int l , r , w ;
#define lt k << 1
#define rt k << 1 | 1
}tree[N << 2] ;
不要问我为啥(<<2)
因为我也不知道线段树的数组大小通常是(N)的(4)倍
inline void build(int k,int l,int r) {
if(l > r) return ;
if(l == r) {
tree[k].l = l , tree[k].r = r , tree[k].w = a[l] ;
return ;
}
int mid = (l + r) >> 1 ;//分治Here
build(lt , l , mid) ;
build(rt , mid + 1 , r) ;
tree[k].l = l , tree[k].r = r ;
tree[k].w = min(tree[lt].w , tree[rt].w) ;
}
建完树之后我们需要做一个操作 : (query)(当然只是函数名我个人喜欢这种函数名)
inline int query(int k,int l,int r,int x,int y) {
if(l > r) return 0 ;
if(l >= x and r <= y) return tree[k].w ;
int mid = (l + r) >> 1 ;
int sum = inf ;
if(x <= mid) sum = min(sum , query(lt , l , mid , x , y)) ;//分治
if(y > mid) sum = min(sum , query(rt , mid + 1 , r , x , y)) ;
return sum ;
}
所以易证时间复杂度 $O(nlog n) $
空间复杂度 (O(N*4))
#include <bits/stdc++.h>
using namespace std ;
inline int rd() { int x = 0 ; int f = 1 ; register char c ;
#define gc c = getchar()
while(isspace(gc)) ;
if(c == '-') f = -1 , gc ;
while(x = (x<<1) + (x<<3) + (c&15) , isdigit(gc)) ;
return x * f ;
#undef gc
}
const int inf = INT_MAX >> 1 ;
const int N = 2e6 + 10 ;
struct node {
int l , r , w ;
#define lt k << 1
#define rt k << 1 | 1
}tree[N << 2] ;
int n , m ;
int a[N] ;
inline void build(int k,int l,int r) {
if(l > r) return ;
if(l == r) {
tree[k].l = l , tree[k].r = r , tree[k].w = a[l] ;
return ;
}
int mid = (l + r) >> 1 ;
build(lt , l , mid) ;
build(rt , mid + 1 , r) ;
tree[k].l = l , tree[k].r = r ;
tree[k].w = min(tree[lt].w , tree[rt].w) ;
}
inline int query(int k,int l,int r,int x,int y) {
if(l > r) return 0 ;
if(l >= x and r <= y) return tree[k].w ;
int mid = (l + r) >> 1 ;
int sum = inf ;
if(x <= mid) sum = min(sum , query(lt , l , mid , x , y)) ;
if(y > mid) sum = min(sum , query(rt , mid + 1 , r , x , y)) ;
return sum ;
}
signed main() {
n = rd() , m = rd() ;
for(register int i=1;i<=n;i++) a[i] = rd() ;
build(1 , 1 , n) ;
for(register int i=1;i<=n;i++) {
int x = i - m , y = i - 1 ;
if(x <= 0) x = 1 ;
if(x > y) {
puts("0") ;
continue ;
}
printf("%d
" , query(1 , 1 , n , x , y)) ;
}
return 0 ;
}