大体题意:
给你n 个数,要求选择一个区间l,r 使得 l~r 之间的数a[i] 满足 a[l] < a[i] < a[r] 求最大的r-l?
思路:
rmq+预处理!
我们可以枚举区间的左端点l,我们需要找到左端点l 的右方第一个小于等于a[l]的位置k,然后我们求出 l ~ k-1区间内的最大值a[pos],如果最大值大于a[l],那么 pos - l 就是答案之一,更新一下最大值即可!
那么问题来了:
rmq求的是 区间内的最大值,但是我们这个题目不仅要求出最大值,还要求出最大值所在的位置!
其实也很好解决,稍微改动一下rmq 即可! 我们让rmq 中的dp[i][j] 记录的是 第i 个位置开始 长度为(1<<j) 的最大值所在位置,这样两个问题就都解决了,注意 如果rmq中两个区间 左边的最大值和右边的最大值相等的话要记录左端点的最大值,否则右边最大值会和左边最大值冲突,解不合法!
然后就是如何求出每一个位置 的右方第一个小于等于他的位置?
我们开一个数组预处理,令r[i]为第i 个位置右方第一个小于等于a[i]的位置! 为了方便,我们可以在原始数据的末尾在加一个-inf 无限小!
那么如果a[i] >= a[i+1]直接r[i] = i + 1;
否则就让他一直往后跳,跳到头为止!
详细见代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 50000 + 7;
const int inf = 0x3f3f3f3f;
int a[maxn];
int dp[maxn][20], n, r[maxn];
void rmq(){
for (int i = 0; i < n; ++i) dp[i][0] = i;
for (int j = 1; (1 << j) <= n; ++j){
for (int i = 0; i + (1 << j) - 1 < n; ++i){
int t1 = dp[i][j-1];
int t2 = dp[i+(1<<(j-1))][j-1];
if (a[t1] >= a[t2]) dp[i][j] = t1;
else dp[i][j] = t2;
}
}
}
int query(int l,int r){
int k = 0;
while((1 << (k+1) ) <= r-l + 1)++k;
int t1 = dp[l][k];
int t2 = dp[r-(1<<k)+1][k];
if (a[t1] >= a[t2]) return t1;
return t2;
}
int main(){
while(scanf("%d",&n) == 1){
for (int i = 0; i < n; ++i){
scanf("%d",&a[i]);
}
rmq();
a[n] = -inf;
r[n-1] = n;
for (int i = n-2; ~i; --i){
if (a[i] >= a[i+1]) r[i] = i+1;
else{
int cur = i+1;
while(1){
if (a[cur] <= a[i]){
r[i] = cur;
break;
}
cur = r[cur];
}
}
}
int ans = 0;
for (int i = 0; i < n; ++i){
int id = query(i,r[i]-1);
if (a[id] > a[i]) ans = max(ans,id-i);
}
if (!ans)printf("-1\n");
else printf("%d\n",ans);
}
return 0;
}
Sticks Problem
Time Limit: 6000MS | Memory Limit: 65536K | |
Total Submissions: 10430 | Accepted: 2771 |
Description
Xuanxuan has n sticks of different length. One day, she puts all her sticks in a line, represented by S1, S2, S3, ...Sn. After measuring the length of each stick Sk (1 <= k <= n), she finds that for some sticks Si and Sj (1<= i < j <= n), each stick placed between Si and Sj is longer than Si but shorter than Sj.
Now given the length of S1, S2, S3, …Sn, you are required to find the maximum value j - i.
Now given the length of S1, S2, S3, …Sn, you are required to find the maximum value j - i.
Input
The input contains multiple test cases. Each case contains two lines.
Line 1: a single integer n (n <= 50000), indicating the number of sticks.
Line 2: n different positive integers (not larger than 100000), indicating the length of each stick in order.
Line 1: a single integer n (n <= 50000), indicating the number of sticks.
Line 2: n different positive integers (not larger than 100000), indicating the length of each stick in order.
Output
Output the maximum value j - i in a single line. If there is no such i and j, just output -1.
Sample Input
4 5 4 3 6 4 6 5 4 3
Sample Output
1 -1
Source
POJ Monthly,static