最近BZOJ炸了,而我的博客上又更新了一些基本知识,所以这里刷一些裸题,用以丰富知识性博客
POJ2823 滑动的窗口
这是一道经典的单调队题,我记得我刚学的时候就是用这道题作为单调队列的例题,算一道比较基本的题目
先贴题目
Description
An array of size n ≤ 106 is given to you. There is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves rightwards by one position. Following is an example:
The array is [1 3 -1 -3 5 3 6 7], and k is 3.
The array is [1 3 -1 -3 5 3 6 7], and k is 3.
Window position | Minimum value | Maximum value |
---|---|---|
[1 3 -1] -3 5 3 6 7 | -1 | 3 |
1 [3 -1 -3] 5 3 6 7 | -3 | 3 |
1 3 [-1 -3 5] 3 6 7 | -3 | 5 |
1 3 -1 [-3 5 3] 6 7 | -3 | 5 |
1 3 -1 -3 [5 3 6] 7 | 3 | 6 |
1 3 -1 -3 5 [3 6 7] | 3 | 7 |
Your task is to determine the maximum and minimum values in the sliding window at each position.
Input
The input consists of two lines. The first line contains two integers n and k which are the lengths of the array and the sliding window. There are n integers in the second line.
Output
There are two lines in the output. The first line gives the minimum values in the window at each position, from left to right, respectively. The second line gives the maximum values.
Sample Input
8 3
1 3 -1 -3 5 3 6 7
Sample Output
-1 -3 -3 -3 3 3 3 3 5 5 6 7
这道题的题目经过思考发现是关于决策的,而状态的转移又有固定的模式,所以是DP。
那么DP方程是什么捏?
这个经思考很好得出f[i]=max(f[i],a[k])和g[i]=min(g[i],a[k]),k都是从i-k+1到i;
那么显然的,这个方法不TLE就见鬼了。虽然题目给了你12秒但是你也不能这样胡做
所以我们考虑更优的解法;
很容易看出来,我们原方程的每个i的决策与前一个或后一个决策都有k-1个决策重复,而对于每一个决策k的结果,都和i无关,所以我们可以优化这一过程。
因为当我们更新完第i个位置的最优解的时候,下一个元素的最优解可以用只判断一个元素来更新。
所以就可以用单调队列了啊(不会的面壁)。
然后愉快的贴出代码。
1 #include<cstdio> 2 #include<cstring> 3 int quq[1100000],ass,n,k,star,a[1100000],time[1100000]; 4 int main() 5 { 6 7 scanf("%d%d",&n,&k); 8 for(int i=1;i<=n;i++)scanf("%d",a+i); 9 star=1,ass=1; 10 quq[star]=a[1]; 11 time[ass]=1; 12 for(int i=2;i<=k;i++) 13 { 14 while(a[i]<=quq[ass]&&ass>=star)--ass; 15 quq[++ass]=a[i]; 16 time[ass]=i; 17 } 18 printf("%d ",quq[star]); 19 for(int i=k+1;i<=n;i++) 20 { 21 if(time[star]<=i-k)star++; 22 while(a[i]<=quq[ass]&&ass>=star)--ass; 23 quq[++ass]=a[i]; 24 time[ass]=i; 25 printf("%d ",quq[star]); 26 } 27 printf(" "); 28 star=1,ass=1; 29 quq[star]=a[1]; 30 time[ass]=1; 31 for(int i=2;i<=k;i++) 32 { 33 while(a[i]>=quq[ass]&&ass>=star)--ass; 34 quq[++ass]=a[i]; 35 time[ass]=i; 36 } 37 printf("%d ",quq[star]); 38 for(int i=k+1;i<=n;i++) 39 { 40 if(time[star]<=i-k)star++; 41 while(a[i]>=quq[ass]&&ass>=star)--ass; 42 quq[++ass]=a[i]; 43 time[ass]=i; 44 printf("%d ",quq[star]); 45 } 46 return 0; 47 }