2 4 2 3 1 2 4 10 5 0 3 4 5 2 1 6 7 8 9
5 28HintFirst Sample, the satisfied groups include:[1,1]、[2,2]、[3,3]、[4,4] 、[2,3]
题目大意:给出一个数列,问其中存在多少连续子序列,子序列的最大值-最小值<k
O(n)的时间复杂度,,,,单调队列太牛叉
用单调队列维护最大值最小值,双指针,第一个第二个指针初始指向第一个数据,第一个指针按顺序不断向队尾添加数据,当最大值最小值的差大于等于k后,就意味着新添加的这个不能作用于当前第二个指针的位置,也就能计算出,以第二个指针位置开始的连续子序列的个数,最后统计总和。
#include <cstdio> #include <cstring> #include <queue> #include <algorithm> using namespace std ; #define LL __int64 deque <LL> deq1 , deq2 ; //单调队列,deq1最大值,deq2最小值 LL a[100010] ; int main() { int t , n , i , j ; LL k , ans ; scanf("%d", &t) ; while( t-- ) { scanf("%d %I64d", &n, &k) ; for(i = 0 ; i < n ; i++) scanf("%I64d", &a[i]) ; if(k == 0) { printf("0\n") ; continue ; } while( !deq1.empty() ) deq1.pop_back() ; while( !deq2.empty() ) deq2.pop_back() ; for(i = 0 , j = 0 , ans = 0; i < n ; i++) {//i在前,j在后 while( !deq1.empty() && deq1.back() < a[i] ) deq1.pop_back() ; deq1.push_back(a[i]) ; while( !deq2.empty() && deq2.back() > a[i] ) deq2.pop_back() ; deq2.push_back(a[i]) ; while( !deq1.empty() && !deq2.empty() && deq1.front() - deq2.front() >= k ) { ans += (i-j) ; //printf("%d %d,%I64d %I64d\n", i , j, deq1.front() , deq2.front() ) ; if( deq1.front() == a[j] ) deq1.pop_front() ; if( deq2.front() == a[j] ) deq2.pop_front() ; j++ ; } } while( j < n ) { ans += (i-j) ; j++ ; } printf("%I64d\n", ans) ; } return 0 ; }