• 洛谷P1886 滑动窗口


    传送门啦

    以最大值为例,既然我们想要保证队列开头为答案,那么我们就要保证每次更新使最大值一直放在队列。那么如果存储的最大值该弹出了怎么办呢?我们只需要记录下每个元素的位置,判断是否在区间内即可。

    队头弹出后,第二位就变成了队头,我们就要保证这个数现在是区间内最大。那么是不是说,我们需要将这个长度为 $ k $ 的区间中的每一个数都存起来呢?不是的,并不是每个数被记录都有意义的。举个例子, $ a_i $ 和 $ a_j $ 两个数, $ i<j $ 。如果 $a_i >a_j $,那么两个数都应该记录;但是如果 $ a_i≤a_j $ ,那么当 $ a_j $ 进入区间后, $ a_i $ 的记录就没有意义了。很好理解,我们假设每个数作为区间最大值的次数为它的贡献,当 $ a_j $ 进入区间以后,在区间中存在的时间一定比 $ a_i $ 长,也就说明 $ a_i $ 一定不会再做贡献了,我们确定没有贡献的点,便可以直接删去,以维护单调队列的单调性。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    #include <cmath>
    #define re register
    using namespace std ;
    const int maxn = 1e6 + 5 ;
    
    inline int read () {
    	int f = 1 , x = 0 ;
    	char ch = getchar () ;
    	while ( ch > '9' || ch < '0' ) {if(ch == '-') f = -1 ; ch = getchar () ; }
    	while ( ch >= '0' && ch <= '9' ) {x = (x << 1) + (x << 3) + ch - '0' ; ch = getchar () ; }
    	return x * f ;
    }
    
    int n , k , a[maxn] ;
    int head = 1 , tail ;
    
    struct Node {
    	int val , pos ;
    }q[maxn] ;
    
    int main () {
    	n = read () ; k = read () ;
    	for(re int i = 1 ; i <= n ; ++ i) {a[i] = read () ;}
    	for(re int i = 1 ; i <= n ; ++ i) {
    		while(head <= tail && q[head].pos + k <= i)  ++head ;
    		while(head <= tail && q[tail].val >= a[i]) --tail ;
    		q[++tail].val = a[i] ;
    		q[tail].pos = i ;
    		if(i >= k)  printf("%d " , q[head].val) ;
    	}
    	head = 1 , tail = 0 ;
    	printf("
    ") ;
    	for(re int i = 1 ; i <= n ; ++ i) {
    		while(head <= tail && q[head].pos + k <= i) ++head ;
    		while(head <= tail && q[tail].val <= a[i]) --tail ;
    		q[++tail].val = a[i] ;
    		q[tail].pos = i ;
    		if(i >= k) printf("%d " , q[head].val) ;
    	}
    	return 0 ;
    }
    
  • 相关阅读:
    div定位
    学习进度条(第十周)
    学习进度条(第九周)
    软件工程个人作业--找水王
    个人NABCD
    梦断代码阅读笔记01---死定了
    进度条(第八周)
    学习进度条(第七周)
    软件工程结对开发作业02---二维数组求最大连通子数组
    软件工程结对作业01--四则运算Web版
  • 原文地址:https://www.cnblogs.com/Stephen-F/p/10414883.html
Copyright © 2020-2023  润新知