【洛谷】【线段树】P1886 滑动窗口

【题目描述:】

现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口。现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值。

【输入格式:】

输入一共有两行,第一行为n,k。

第二行为n个数(<INT_MAX).

【输出格式:】

输出共两行,第一行为每次窗口滑动的最小值

第二行为每次窗口滑动的最大值

输入样例#18 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('\n');
50     for(int i = 1; i <= n - k + 1; ++i) printf("%d ", ans1[i]);
51 }

 

posted @ 2018-05-15 21:40  DEVILK  阅读(254)  评论(0编辑  收藏  举报