SPOJ Fata7y Ya Warda! 裸单调栈 1月25日

来源:互联网 发布:成都妇女儿童医院网络 编辑:程序博客网 时间:2024/06/06 08:49

题目链接: https://vjudge.net/problem/SPOJ-DRUIDEOI
题意:
题意
n个数形成一个环,定义1号的左边是n号,位置i的数值为hi。
输出每一个数左边和右边,第一个比他大的数的位置,如果不存在这样的位置,输出-1。
数据
测试样例数T, (1 <= T <= 20)。
(1 <= n <= 1e5,1 <= hi <= 1e9)。
输入
3
5
172 170 168 171 169
3
172 169 172
1
172
输出
-1 -1
1 4
2 4
1 1
4 1
-1 -1
1 3
-1 -1
-1 -1

解题方法:
因为数字是一个圈而不是一条线。所以第一步是把数组倍增(用来模拟圈)。好,现在问题变成了如何求前面和后面第一个比它大的。这件事情可以用单调栈做。

代码如下:

#include <bits/stdc++.h>using namespace std;#define rep(i, a, b) for(int i = a; i <= b; i++)#define uep(i, a, b) for(int i = a; i >= b; i--)#define cls(a, b) memset(a, b, sizeof(a))const int maxn = 300010;int a[maxn], L[maxn], R[maxn], T, n;int stk[maxn], top;int main(){    int T;    scanf("%d", &T);    while(T--){        scanf("%d", &n);        cls(L, 0); cls(R, 0);        top = 0;        rep(i, 1, n) scanf("%d", &a[i]), a[i + n] = a[i];        rep(i, 1, 2*n){            if(!top) L[i] = -1, stk[++top] = i;            else if(a[i] >= a[stk[top]]){                while(top > 0 && a[i] >= a[stk[top]]) --top;                if(top != 0) L[i] = stk[top];                else L[i] = -1;                stk[++top]  = i;            }            else L[i] = stk[top], stk[++top] = i;        }        top = 0;        uep(i, 2*n, 1){            if(!top) R[i] = -1, stk[++top] = i;            else if(a[i] >= a[stk[top]]){                while(top != 0 && a[i] >= a[stk[top]]) --top;                if(top != 0) R[i] = stk[top];                else R[i] = -1;                stk[++top] = i;            }            else R[i] = stk[top], stk[++top] = i;        }        rep(i, n + 1, n*2){            if(L[i] <= n) printf("%d ", L[i]);            else printf("%d ", L[i] - n);            if(R[i - n] <= n) printf("%d\n", R[i - n]);            else printf("%d\n", R[i - n] - n);        }    }    return 0;}
0 0