CodeForces 91B Queue

题目链接:http://codeforces.com/contest/91/problem/B

题目大意:

  有n头大象排队买票,第i头大象的年龄为ai,如果有比他年轻的大象排在他前面,这头大象就会非常不高兴,衡量不高兴度的指标是这只大象与排在前面的最远的比它年轻的大象之间的大象数量。输出每只大象的不高兴度,如果没有不高兴,输出-1。

分析:

单调栈+愉快的二分
这道题是求最远小的问题,而单调栈只能求最近小,我思考了半天能不能把最近小改造成求最远小,结果很是徒劳。
随后我发现,求第i只大象右边的最远小,难道不就是把大象拎到队伍最右边,然后求它左边的最近小吗?也就是说只要让队伍过一下单调栈(我用数组实现的),然后对于每头大象,在单调栈里剩下来的元素中做一次二分查找(查找第一个比他小的)即可。

代码如下:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3  
 4 #define rep(i,n) for (int i = 0; i < (n); ++i)
 5 #define For(i,s,t) for (int i = (s); i <= (t); ++i)
 6 #define rFor(i,t,s) for (int i = (t); i >= (s); --i)
 7 #define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
 8 #define rforeach(i,c) for (__typeof(c.rbegin()) i = c.rbegin(); i != c.rend(); ++i)
 9  
10 #define pr(x) cout << #x << " = " << x << "  "
11 #define prln(x) cout << #x << " = " << x << endl
12  
13 #define ALL(x) x.begin(),x.end()
14 #define INS(x) inserter(x,x.begin())
15  
16 #define ms0(a) memset(a,0,sizeof(a))
17 #define msI(a) memset(a,inf,sizeof(a))
18 #define msM(a) memset(a,-1,sizeof(a))
19  
20 #define pii pair<int,int> 
21 #define piii pair<pair<int,int>,int> 
22 #define mp make_pair
23 #define pb push_back
24 #define fi first
25 #define se second
26  
27 inline int gc(){
28     static const int BUF = 1e7;
29     static char buf[BUF], *bg = buf + BUF, *ed = bg;
30      
31     if(bg == ed) fread(bg = buf, 1, BUF, stdin);
32     return *bg++;
33 } 
34  
35 inline int ri(){
36     int x = 0, f = 1, c = gc();
37     for(; c<48||c>57; f = c=='-'?-1:f, c=gc());
38     for(; c>47&&c<58; x = x*10 + c - 48, c=gc());
39     return x*f;
40 }
41  
42 typedef long long LL;
43 typedef unsigned long long uLL;
44 const int inf = 0x3f3f3f3f;
45 const LL infLL = 0x3f3f3f3f3f3f3f3fLL;
46 const LL mod = 1e9 + 7;
47 const int maxN = 1e5 + 7;
48  
49 int n;
50 int a[maxN];
51 int ans[maxN];
52  
53 // 二分查找vector中最右边使得a[x[i]] < k的x[i]值,找不到返回-1 
54 int BinarySearch(vector< int > & x, int k) {
55     if(x.size() == 0 || a[x[0]] >= k) return -1;
56     int l = 0, r = x.size() - 1;
57     int mid = (l + r) >> 1;
58      
59     while(l < r) {
60         if(a[x[mid]] >= k) {
61             r = mid - 1;
62             mid = (l + r) >> 1;
63         }
64         else {
65             l = mid + 1;
66             if(a[x[l]] >= k) return x[mid];
67             mid = (l + r) >> 1;
68         }
69     }
70     return x[r]; 
71 }
72  
73 int main(){
74     while(cin >> n) {
75         For(i, 1, n) cin >> a[i];
76         vector< int > vi;
77          
78         For(i, 1, n) {
79             if(vi.empty() || a[i] > a[vi.back()]) {
80                 vi.push_back(i);
81             }
82             else if(a[i] <= a[vi.back()]) {
83                 vi.pop_back();
84                 --i;
85             }
86         }
87          
88         For(i, 1, n) {
89             ans[i] = BinarySearch(vi, a[i]);
90             ans[i] -= i + 1;
91             if(ans[i] < 0) ans[i] = -1;
92             cout << ans[i] << " ";
93         }
94     }
95     return 0;
96 }
View Code

 

转载于:https://www.cnblogs.com/zaq19970105/p/10752235.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值