洛谷P1886 滑动窗口(POJ.2823 Sliding Window)(区间最值)

Posted SovietPower

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷P1886 滑动窗口(POJ.2823 Sliding Window)(区间最值)相关的知识,希望对你有一定的参考价值。

To 洛谷.1886 滑动窗口 To POJ.2823 Sliding Window

题目描述

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

例如:

The array is [1 3 -1 -3 5 3 6 7], and k = 3.

技术分享

输入输出格式

输入格式:

 

输入一共有两行,第一行为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

说明

50%的数据,n<=10^5

100%的数据,n<=10^6

代码:

洛谷70分TLE的线段树

技术分享
 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 const int N=1000005;
 5 
 6 int n,k,From,To,Min[N<<2],Max[N<<2];
 7 
 8 void read(int &now)
 9 {
10     now=0;int f=1;char c=getchar();
11     while(c<0||c>9)
12     {
13         if(c==-)f=-1;
14         c=getchar();
15     }
16     while(c>=0&&c<=9)now=now*10+c-0,c=getchar();
17     now*=f;
18 }
19 
20 inline void PushUp(int rt)
21 {
22     Min[rt]=min(Min[rt<<1],Min[rt<<1|1]);
23     Max[rt]=max(Max[rt<<1],Max[rt<<1|1]);
24 }
25 
26 void Build(int l,int r,int rt)
27 {
28     if(l==r)
29     {
30         int t;
31         read(t);
32         Min[rt]=Max[rt]=t;
33         return;
34     }
35     int m=(l+r)>>1;
36     Build(l,m,rt<<1);
37     Build(m+1,r,rt<<1|1);
38     PushUp(rt);
39 }
40 
41 int QueryMax(int l,int r,int rt,int L,int R)
42 {
43     if(L<=l && r<=R) return Max[rt];
44     int m=(l+r)>>1,res=(1<<31);
45     if(L<=m) res=max(res,QueryMax(l,m,rt<<1,L,R));
46     if(m<R) res=max(res,QueryMax(m+1,r,rt<<1|1,L,R));
47     return res;
48 }
49 
50 int QueryMin(int l,int r,int rt,int L,int R)
51 {
52     if(L<=l && r<=R) return Min[rt];
53     int m=(l+r)>>1,res=(1<<30);
54     if(L<=m) res=min(res,QueryMin(l,m,rt<<1,L,R));
55     if(m<R) res=min(res,QueryMin(m+1,r,rt<<1|1,L,R));
56     return res;
57 }
58 
59 int main()
60 {
61     read(n);read(k);
62     Build(1,n,1);
63     //From=1;To=k;
64     for(register int i=1;i<=n-k+1;i++)//,From++,To++
65       printf("%d ",QueryMin(1,n,1,i,i+k-1));
66     printf("\n");
67     //From=1;To=k;
68     for(register int i=1;i<=n-k+1;i++)//,From++,To++
69       printf("%d ",QueryMax(1,n,1,i,i+k-1));
70     return 0;
71 }
TLE

常数优化十分可观的zkw线段树(然而我不会用)

技术分享
 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 const int N=1000005;
 5 
 6 int n,k,M,Tree[N<<2];
 7 
 8 void read(int &now)
 9 {
10     now=0;int f=1;char c=getchar();
11     while(c>9||c<0)
12     {
13         if(c==-)f=-1;
14         c=getchar();
15     }
16     while(c>=0&&c<=9)now=(now<<3)+(now<<1)+c-0,c=getchar();
17     now*=f;
18 }
19 
20 void BuildMin(int n)
21 {
22     for(int i=M-1;i;--i)
23       Tree[i]=min(Tree[i<<1],Tree[i<<1|1]);
24 }
25 
26 void BuildMax(int n)
27 {
28     for(int i=M-1;i;--i)
29       Tree[i]=max(Tree[i<<1],Tree[i<<1|1]);
30 }
31 
32 int QueryMin(int s,int t,int res)
33 {
34     for(s+=M,t+=M;s^t^1;s>>=1,t>>=1)
35     {
36         if(~s&1) res=min(res,Tree[s^1]);
37         if(t&1) res=min(res,Tree[t^1]);
38     }
39     return res;
40 }
41 
42 int QueryMax(int s,int t,int res)
43 {
44     for(s+=M,t+=M;s^t^1;s>>=1,t>>=1)
45     {
46         if(~s&1) res=max(res,Tree[s^1]);
47         if(t&1) res=max(res,Tree[t^1]);
48     }
49     return res;
50 }
51 
52 int main()
53 {
54     read(n);read(k);
55     for(M=1;M<=n+1;M<<=1);
56     for(int i=M+1;i<=M+n;i++)
57       read(Tree[i]);
58     BuildMin(n);
59     for(int i=0;i<=n-k;++i)
60       printf("%d ",QueryMin(i,i+k+1,1e9));
61     printf("\n");
62     BuildMax(n);
63     for(int i=0;i<=n-k;++i)
64       printf("%d ",QueryMax(i,i+k+1,-1e9));
65     return 0;
66 }
AC

 

以上是关于洛谷P1886 滑动窗口(POJ.2823 Sliding Window)(区间最值)的主要内容,如果未能解决你的问题,请参考以下文章

洛谷 P1886 滑动窗口

洛谷P1886滑动窗口

洛谷 P1886 滑动窗口

洛谷P1886 滑动窗口 单调队列

洛谷P1886滑动窗口

AC日记——滑动窗口 洛谷 P1886