Sticks Problem
题目链接:
http://poj.org/problem?id=2452
解题思路:
题目大意:
给你一组数a[n],求满足a[i] < a[k] < a[j] (i <= k <= j)的最大的j-i。
算法思想:
RMQ + 二分。
枚举i,利用二分求出a[i]右边第一个小于a[i]的数的位置k,
再求出[i, k]中最大值的位置j,若a[j] > a[i],则更新结果。
AC代码:
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
const int maxn = 50005;
int n,len[maxn];
// 分别存储的是最大值和最小值的下标
int minl[maxn][20], maxl[maxn][20];
int _max(int l, int r){
if(len[l] > len[r])
return l;
return r;
}
int _min(int l, int r){
if(len[l] < len[r])
return l;
return r;
}
void init_RMQ(){
for(int i = 1; i <= n; ++i)
minl[i][0] = maxl[i][0] = i;
int l = int(log((double)n)/log(2.0));
for(int j = 1; j <= l; j++){
for(int i = 1; i + (1 << (j-1)) - 1 <= n;++i){
maxl[i][j] = _max(maxl[i][j-1], maxl[i + (1 << (j-1))][j-1]);
minl[i][j] = _min(minl[i][j-1], minl[i + (1 << (j-1))][j-1]);
}
}
}
int maxRMQ(int l, int r){
int k = (int)(log(double(r) - l + 1) / log(2.0));
return _max(maxl[l][k], maxl[r - (1<<k) + 1][k]);
}
int minRMQ(int l, int r){
int k = (int)(log(double(r) - l + 1) / log(2.0));
return _min(minl[l][k], minl[r - (1<<k) + 1][k]);
}
int bsearch(int x, int l, int r){
while(l <= r){
if(l == r)
return l;
int m = (l + r) >> 1;
if (len[x] < len[minRMQ(l, m)])
l = m + 1;
else r = m;
}
}
void solve(){
int ans = 0;
for(int i = 1; i + ans < n; ++i){
int r = bsearch(i, i + 1, n);
int k = maxRMQ(i, r);
if(len[k] > len[i])
ans = max(ans, k - i);
}
if(ans == 0)
printf("-1\n");
else
printf("%d\n",ans);
}
int main(){
while(~scanf("%d",&n)){
for(int i = 1; i <= n; ++i)
scanf("%d",&len[i]);
init_RMQ();
solve();
}
return 0;
}