您的位置:首页 > 其它

POJ 2452 Sticks Problem ★ (单调栈+RMQ)

2013-02-20 02:07 295 查看
题目大意:给出一串数,找到最长的一个连续子区间,使得区间的头元素为区间内最小值,末元素为区间内最大值。长度L<=50000

挺好的一道题,自己没想出来T T……看题解才受到了启发……

用单调栈,预处理所有点的一个right[i],表示i点向后扩展到的最远的以height[i]为最小值的区间。

然后用RMQ求每个区间的最大值的位置。(这里我用的线段树实现的……不会ST,神牛鄙视我吧……)

于是我们先用单调栈求出right[i]数组,然后对于i~right[i]的区间,求出最大值所在位置p,i~p就为i向后能扩展到的最远的一个区间。对于每个点都向后查询一次,就能求出最优解。复杂度O(NlgN)。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MID(x,y) ((x+y)>>1)
using namespace std;
typedef long long LL;

int height[50005], right[50005];
int maxn[200005];
void pushup(int rt){
maxn[rt] = max(maxn[rt<<1], maxn[rt<<1|1]);
return ;
}
void debug_tree(int l, int r, int rt){
if (l == r){
printf("%d %d %d\n", rt, l, maxn[rt]);
return ;
}
int mid = MID(l, r);
debug_tree(l, mid, rt<<1);
debug_tree(mid+1, r, rt<<1|1);
return ;
}
void build_tree(int l, int r, int rt){
if (l == r){
maxn[rt] = height[l];
return ;
}
int mid = MID(l, r);
build_tree(l, mid, rt<<1);
build_tree(mid+1, r, rt<<1|1);
pushup(rt);
return ;
}
int query_max(int s, int t, int l, int r, int rt){
if (s <= l && r <= t){
return maxn[rt];
}
int mid = MID(l,r);
int ans = 0;
if (s <= mid)   ans = max(ans, query_max(s, t, l, mid, rt<<1));
if (mid < t)    ans = max(ans, query_max(s, t, mid+1, r, rt<<1|1));
return ans;
}
int query_position(int s, int t, int l, int r, int rt){
if (l == r){
return l;
}
int mid = MID(l,r);
int max1 = 0, max2 = 0;
if (s <= mid)   max1 = query_max(s, t, l, mid, rt<<1);
if (mid < t)    max2 = query_max(s, t, mid+1, r, rt<<1|1);
if (max1 > max2)
return query_position(s, t, l, mid, rt<<1);
else
return query_position(s, t, mid+1, r, rt<<1|1);
}
stack  S;
int main(){
int n;
while(scanf("%d", &n) == 1){
for (int i = 1; i <= n; i ++)
scanf("%d", &height[i]);
build_tree(1, n, 1);
//debug_tree(1, n, 1);
while(!S.empty())
S.pop();
height[n+1] = -1;
for (int i = 1; i <= n + 1; i ++){
if (S.empty() || height[S.top()] < height[i]){
S.push(i);
}
else{
while(!S.empty() &&height[S.top()] >= height[i]){
right[S.top()] = i;
S.pop();
}
S.push(i);
}
}
int res = 0;
for (int i = 1; i <= n; i ++){
//printf("%d %d\n", i, right[i]);
res = max(res, query_position(i, right[i]-1, 1, n, 1) - i );
}
if (res == 0)
printf("-1\n");
else    printf("%d\n", res);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: