【COGS495】窗口

【问题描述】

给你一个长度为N的数组,一个长为K的滑动的窗体从最左移至最右端,你只能见到窗口的K个数,每次窗体向右移动一位,如下表:

Window positionMin valueMax value
[1 3 -1] -3 5 3 6 7-13
1 [3 -1 -3] 5 3 6 7-33
1 3 [-1 -3 5]3 6 7-35
1 3 -1 [-3 5 3] 6 7-35
1 3 -1 -3 [5 3 6] 736
1 3 -1 -3 5 [3 6 7 ]37


你的任务是找出窗口在各位置时的max value,min value.

 

【输入格式】

第一行n,k,第二行为长度为n的数组

 

【输出格式】

第一行每个位置的min value,第二行每个位置的max value

 

【分析】

好吧,其实我不想发上来的,纯粹凑数。

裸的单调队列。

 

 1 #include <cstdlib>
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cmath>
 5 #include <algorithm>
 6 #include <cstring>
 7 const int maxn=1000010;
 8 const int INF=0x7fffffff;
 9 using namespace std;
10 struct que{int shu[maxn],l,r;}Q_max,Q_min; 
11 void solve();
12 void print(); 
13 int data[maxn],n,k;
14 int ans[2][maxn];
15 
16 int main()
17 {
18     //文件操作
19     freopen("window.in","r",stdin);
20     freopen("window.out","w",stdout); 
21     scanf("%d%d",&n,&k);
22     for (int i=1;i<=n;i++) scanf("%d",&data[i]);
23     solve();//滑动窗口
24     print();//打印 
25     return 0;
26 }
27 void solve()
28 {
29      //拉上窗口
30      int i;
31      Q_max.l=Q_min.l=Q_max.r=Q_min.r=1;//初始化指针 
32      for (i=1;i<=k;i++) 
33      {
34          while (Q_max.l<Q_max.r && Q_max.shu[Q_max.l]<i-k+1) Q_max.l++;
35          while (Q_min.l<Q_min.r && Q_min.shu[Q_min.l]<i-k+1) Q_min.l++;
36          while (Q_max.l<Q_max.r && data[Q_max.shu[Q_max.r-1]]<data[i]) Q_max.r--;
37          while (Q_min.l<Q_min.r && data[Q_min.shu[Q_min.r-1]]>data[i]) Q_min.r--;
38          Q_max.shu[Q_max.r++]=i;Q_min.shu[Q_min.r++]=i;
39      }
40      //注意窗口永远指向窗口最右端 
41      for (i=k;i<=n;i++) 
42      {
43          while (Q_max.l<Q_max.r && Q_max.shu[Q_max.l]<i-k+1) Q_max.l++;
44          while (Q_min.l<Q_min.r && Q_min.shu[Q_min.l]<i-k+1) Q_min.l++;
45          ans[0][i]=Q_max.shu[Q_max.l];ans[1][i]=Q_min.shu[Q_min.l];//标记打印 
46          while (Q_max.l<Q_max.r && data[Q_max.shu[Q_max.r-1]]<data[i+1]) Q_max.r--;
47          while (Q_min.l<Q_min.r && data[Q_min.shu[Q_min.r-1]]>data[i+1]) Q_min.r--;
48          Q_max.shu[Q_max.r++]=i+1;Q_min.shu[Q_min.r++]=i+1;
49      }
50 }
51 void print()
52 {
53      for (int i=k;i<=n;i++) printf("%d ",data[ans[1][i]]);
54      printf("\n");
55      for (int i=k;i<=n;i++) printf("%d ",data[ans[0][i]]);
56 }

 

转载于:https://www.cnblogs.com/hoskey/p/3762337.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值