【题目描述:】
现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口。现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值。
【输入格式:】
输入一共有两行,第一行为n,k。
第二行为n个数(<INT_MAX).
【输出格式:】
输出共两行,第一行为每次窗口滑动的最小值
第二行为每次窗口滑动的最大值

输入样例#1: 8 3 1 3 -1 -3 5 3 6 7 输出样例#1: -1 -3 -3 -3 3 3 3 3 5 5 6 7
【算法分析:】
线段树使用结构体同时维护区间最小值和最大值
没有修改只有建树和查询操作,更优的方法是使用st表做RMQ
板子题.
【代码:】
1 //滑动窗口 2 #include<iostream> 3 #include<cstdio> 4 using namespace std; 5 6 const int MAXN = 1e6 + 1; 7 8 int n, k; 9 int a[MAXN]; 10 struct Segment { 11 int maxn, minn; 12 }t[MAXN << 2]; 13 14 void Build(int o, int l, int r) { 15 if(l == r) t[o].maxn = t[o].minn = a[l]; 16 else { 17 int mid = (l + r) >> 1; 18 Build(o << 1, l , mid); 19 Build(o << 1|1, mid + 1, r); 20 t[o].maxn = max(t[o << 1].maxn, t[o << 1|1].maxn); 21 t[o].minn = min(t[o << 1].minn, t[o << 1|1].minn); 22 } 23 } 24 int max_ans, min_ans; 25 void Query(int o, int l, int r, int ql, int qr) { 26 if(ql <= l && r <= qr) { 27 max_ans = max(max_ans, t[o].maxn); 28 min_ans = min(min_ans, t[o].minn); 29 } 30 else { 31 int mid = (l + r) >> 1; 32 if(ql <= mid) Query(o << 1, l, mid, ql, qr); 33 if(qr > mid) Query(o << 1|1, mid + 1, r, ql, qr); 34 } 35 } 36 37 int ans1[MAXN], ans2[MAXN]; 38 int main() { 39 scanf("%d%d", &n, &k); 40 for(int i = 1; i <= n; ++i) 41 scanf("%d", &a[i]); 42 Build(1, 1, n); 43 for(int i = 1; i + k - 1 <= n; ++i) { 44 max_ans = -2e9, min_ans = 2e9; 45 Query(1, 1, n, i, i + k - 1); 46 ans1[i] = max_ans, ans2[i] = min_ans; 47 } 48 for(int i = 1; i <= n - k + 1; ++i) printf("%d ", ans2[i]); 49 putchar(' '); 50 for(int i = 1; i <= n - k + 1; ++i) printf("%d ", ans1[i]); 51 }