Problem I. Wiki with Special Poker Cards

Problem I. Wiki with Special Poker Cards
Input file: standard input Time limit: 1 second
Output file: standard output Memory limit: 256 megabytes
"耶,我赢了! "教室里传来一阵阵快乐的笑声。这是在干什么呢?原来他们在举行"扑克牌游戏"呢。而
作为本次游戏的组织者, Wiki也同时制定了游戏的规则,规则如下:
游戏现场一共有n张扑克牌,但是有别于传统的扑克牌,本次游戏所采用的扑克牌,其牌面大小都在整数
区间[1; 106]之内。把这n张扑克牌按照从左往右的顺序平放在桌子上,牌面大小依次为a1; a2; :::; an
现在请游戏参与者从这n张扑克牌中挑出连续的m张扑克,满足这m张扑克中牌面最大的那张ai与最小的
那张aj(1 <= i; j <= n)的差值小于等于r,且这m张扑克的牌面加起来的和大于等于s
游戏期间,同学们依次上场,每人游戏结束以后, Wiki会记录每位同学拿到的牌数m,且每位游戏参与
者拿到的这m张牌必须符合上述游戏规则,不符合规则则记录为0
为了保证游戏的公平性,每人游戏结束以后, Wiki会把这n张牌重新摆放到初始位置,保证每位参与游
戏的同学都能在相同的条件下进行游戏。最后,谁拿到的牌数最多(也就是m),谁就赢得游戏胜利。
Input
第一行输入三个正整数n; r; s(1 <= n <= 105; 0 <= r; s <= 106)
接下来输入n个正整数ai(1 <= i <= n),两数之间用空格隔开,表示n张牌牌面的大小(0 <= ai <= 106)
Output
在满足游戏规则的前提下,输出m的最大值
Samples

standard input standard output
5 0 5
1 1 1 1 1
5
5 3 10
1 2 3 4 5
4



思路:

利用两个单调队列,一个维护以i为终止节点的单调不减队列记录区间最小值,另一个维护以i为终止节点的单调不增队列记录区间最大值

用一个指针记录满足最大值最小值的最小下标,如果该区间满足前缀和要求,则用该区间去更新答案,否则不更新

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <deque>
 5 
 6 
 7 using namespace std ;
 8 
 9 const int N = 100010 ;
10 deque<int> miv,mav ;
11 
12 int a[N],sum[N] ;
13 int n,r,s ;
14 
15 
16 int main(){
17     cin >> n >> r >> s ;
18     
19     for(int i=1;i<=n;i++){
20         cin >> a[i] ;
21         sum[i] = sum[i-1] + a[i] ;
22     }
23     
24     int last = 0, ans = 0 ;
25     for(int i=1;i<=n;i++){
26         while(!mav.empty() && a[mav.back()] < a[i]) mav.pop_back() ;
27         while(!miv.empty() && a[miv.back()] > a[i]) miv.pop_back() ;
28         mav.push_back(i) ;
29         miv.push_back(i) ;
30         while(!miv.empty() && !mav.empty() && a[mav.front()] - a[miv.front()] > r){
31             if(mav.front()<miv.front()){
32                 last = mav.front() ;
33                 mav.pop_front() ;
34             }else if(mav.front()>miv.front()){
35                 last = miv.front() ;
36                 miv.pop_front() ;
37             }else{
38                 last = mav.front() ;
39                 mav.pop_back() ;
40                 miv.pop_back() ;
41             }
42         }
43         if(!mav.empty() && !miv.empty() && sum[i]-sum[last]>=s){
44             ans = max(ans,i-last) ;
45         } 
46     }
47     cout << ans << endl ;
48     
49     return 0 ;
50 }

...

原文地址:https://www.cnblogs.com/gulangyuzzz/p/12075107.html