题目链接:http://codeforces.com/contest/91/problem/B
题目大意:
有n头大象排队买票,第i头大象的年龄为ai,如果有比他年轻的大象排在他前面,这头大象就会非常不高兴,衡量不高兴度的指标是这只大象与排在前面的最远的比它年轻的大象之间的大象数量。输出每只大象的不高兴度,如果没有不高兴,输出-1。
分析:
单调栈+愉快的二分
这道题是求最远小的问题,而单调栈只能求最近小,我思考了半天能不能把最近小改造成求最远小,结果很是徒劳。
随后我发现,求第i只大象右边的最远小,难道不就是把大象拎到队伍最右边,然后求它左边的最近小吗?也就是说只要让队伍过一下单调栈(我用数组实现的),然后对于每头大象,在单调栈里剩下来的元素中做一次二分查找(查找第一个比他小的)即可。
代码如下:
#include <bits/stdc++.h>
using namespace std; #define rep(i,n) for (int i = 0; i < (n); ++i)
#define For(i,s,t) for (int i = (s); i <= (t); ++i)
#define rFor(i,t,s) for (int i = (t); i >= (s); --i)
#define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
#define rforeach(i,c) for (__typeof(c.rbegin()) i = c.rbegin(); i != c.rend(); ++i) #define pr(x) cout << #x << " = " << x << " "
#define prln(x) cout << #x << " = " << x << endl #define ALL(x) x.begin(),x.end()
#define INS(x) inserter(x,x.begin()) #define ms0(a) memset(a,0,sizeof(a))
#define msI(a) memset(a,inf,sizeof(a))
#define msM(a) memset(a,-1,sizeof(a)) #define pii pair<int,int>
#define piii pair<pair<int,int>,int>
#define mp make_pair
#define pb push_back
#define fi first
#define se second inline int gc(){
static const int BUF = 1e7;
static char buf[BUF], *bg = buf + BUF, *ed = bg; if(bg == ed) fread(bg = buf, , BUF, stdin);
return *bg++;
} inline int ri(){
int x = , f = , c = gc();
for(; c<||c>; f = c=='-'?-:f, c=gc());
for(; c>&&c<; x = x* + c - , c=gc());
return x*f;
} typedef long long LL;
typedef unsigned long long uLL;
const int inf = 0x3f3f3f3f;
const LL infLL = 0x3f3f3f3f3f3f3f3fLL;
const LL mod = 1e9 + ;
const int maxN = 1e5 + ; int n;
int a[maxN];
int ans[maxN]; // 二分查找vector中最右边使得a[x[i]] < k的x[i]值,找不到返回-1
int BinarySearch(vector< int > & x, int k) {
if(x.size() == || a[x[]] >= k) return -;
int l = , r = x.size() - ;
int mid = (l + r) >> ; while(l < r) {
if(a[x[mid]] >= k) {
r = mid - ;
mid = (l + r) >> ;
}
else {
l = mid + ;
if(a[x[l]] >= k) return x[mid];
mid = (l + r) >> ;
}
}
return x[r];
} int main(){
while(cin >> n) {
For(i, , n) cin >> a[i];
vector< int > vi; For(i, , n) {
if(vi.empty() || a[i] > a[vi.back()]) {
vi.push_back(i);
}
else if(a[i] <= a[vi.back()]) {
vi.pop_back();
--i;
}
} For(i, , n) {
ans[i] = BinarySearch(vi, a[i]);
ans[i] -= i + ;
if(ans[i] < ) ans[i] = -;
cout << ans[i] << " ";
}
}
return ;
}