POJ 2452 (RMQ + 二分)

来源:互联网 发布:部落冲突九本满防数据 编辑:程序博客网 时间:2024/04/30 15:51
Sticks Problem
Time Limit: 6000MS Memory Limit: 65536KTotal Submissions: 10141 Accepted: 2682

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.

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.

Output

Output the maximum value j - i in a single line. If there is no such i and j, just output -1.

Sample Input

45 4 3 646 5 4 3

Sample Output

1-1


题意:
给一个长度为n的序列 
其中 Si ~ Sj (1<= i < j <= n)为其子序列
问:满足Si ~ Sj 中任意一个数大于Si 且 小于Sj的序列中,j - i的值最大为多少。

解题思路:
一开始就没想过暴力,但是其实暴力是可以过的,坑。。。。。

然而我的方法是用RMQ处理出区间最值,然后暴力扫过去,对每一个数 用两次二分找出 这个数所能形成的最大区间。
(先假设起点为i)两次二分作用分别为:
第一次:找出i能作为最小值的最大区间位置(其实这个可以用单调栈来处理)
第二次:在第一次找出的区间内寻找出该区间最大值的位置

#include <iostream>#include <cstdio>#include <cmath>#include <string>#include <cstring>#include <algorithm>#include <queue>#include <map>#include <set>#include <stack>#include <vector>#include <sstream>#define PI acos(-1.0)#define eps 1e-8const int  inf =  (1<<30) - 10;using namespace std;const int maxx = 50000 + 10;int n;int a[maxx];int dpmax[maxx][20];int dpmin[maxx][20];int mn[maxx];inline void init_rmq(int a[],int n){ ///构建rmq    mn[0]=-1;    for(int i = 1;i <= n; ++i){        if((i&(i-1))==0){            mn[i] = mn[i-1]+1;        }else{            mn[i] = mn[i-1];        }        dpmax[i][0] = a[i];        dpmin[i][0] = a[i];    }    for(int j = 1;j <= mn[n]; ++j){        for(int i = 1;i+(1<<j)-1 <= n; ++i){            dpmax[i][j] = max(dpmax[i][j-1],dpmax[i+(1<<(j-1))][j-1]);            dpmin[i][j] = min(dpmin[i][j-1],dpmin[i+(1<<(j-1))][j-1]);        }    }}inline int max_rmq(int l,int r){ //查询区间最大值    int k = mn[r-l+1];    return max(dpmax[l][k],dpmax[r-(1<<k)+1][k]);}inline int min_rmq(int l,int r){ //查询区间最小值    int k = mn[r-l+1];    return min(dpmin[l][k],dpmin[r-(1<<k)+1][k]);}int main(){    while(scanf("%d",&n)==1){        for(int i = 1;i <= n; ++i){            scanf("%d",&a[i]);        }        init_rmq(a,n);        int ans = -1;        for(int i = 1;i <= n; ++i){            int l = i;            int r = n+1;            while(l+1 != r){                int mid = (l+r)>>1;                if(min_rmq(i,mid) == a[i]){                    l = mid;                }else{                    r = mid;                }            }            int ll = i;            int rr = l;            if(l != i){                int temp = max_rmq(ll,rr);                while(ll+1 != rr){                    int mid = (ll+rr)>>1;                    if(max_rmq(i,mid) < temp){                        ll = mid;                    }else{                        rr = mid;                    }                }            }            if(rr-i>ans) ans = rr-i;        }        if(ans) printf("%d\n",ans);        else printf("-1\n");    }    return 0;}/**71 2 3 7 4 5 6*/

如有BUG,请大家务必指出,不胜感激~

E-mail:274489985@qq.com

0 0