给定一个可能含有重复值的数组 arr,找到每一个 i 位置左边和右边离 i 位置最近且值比 arr[i] 小的位置。返回所有位置相应的信息。
                                        
                                            第一行输入一个数字 n,表示数组 arr 的长度。
以下一行输入 n 个数字,表示数组的值
输出n行,每行两个数字 L 和 R,如果不存在,则值为 -1,下标从 0 开始。
7 3 4 1 5 6 2 7
-1 2 0 2 -1 -1 2 5 3 5 2 -1 5 -1
#include<iostream>
#include<stack>
#include<vector>
using namespace std;
int main(void)
{
    int n = 0, num;
    cin >> n;
    stack<int> stk;
    vector<vector<int>> ret(n);
    vector<int> nums(n);
    for(int i = 0; i < n; i++)
    {
        cin >> num;
        nums[i] = num;
        while(!stk.empty() && nums[stk.top()] >= num)
            stk.pop();
        if(stk.empty())
            ret[i] = vector<int>{-1, -1};
        else
            ret[i] = vector<int>{stk.top(), -1};
        stk.push(i);
    }
    while(!stk.empty())
    {
        stk.pop();
    }
    for(int i = n - 1; i >= 0; i--)
    {
        while(!stk.empty() && nums[stk.top()] >= nums[i])
            stk.pop();
        if(stk.empty())
            ret[i][1] = -1;
        else
            ret[i][1] = stk.top();
        stk.push(i);
    }
    for(int i = 0; i < n; i++)
    {
        cout << ret[i][0] << " " << ret[i][1] << endl;
    }
} 超时代码 #include<iostream>
#include<stack>
#include<vector>
#include<cstdio>
using namespace std;
int main(void)
{
    int n = 0;
    cin >> n;
    stack<int> stk;
    vector<vector<int> > ret(n,{-1,-1});
    vector<int> nums(n);
    for(int i = 0; i < n; i++)
    {
        cin >> nums[i];
        while(!stk.empty() && nums[stk.top()] >= nums[i])
            stk.pop();
        if(!stk.empty())
            ret[i][0] = stk.top();
        stk.push(i);
    }
    while(!stk.empty())
    {
        stk.pop();
    }
    for(int i = n - 1; i >= 0; i--)
    {
        while(!stk.empty() && nums[stk.top()] >= nums[i])
            stk.pop();
        if(!stk.empty())
            ret[i][1] = stk.top();
        stk.push(i);
    }
    for(int i = 0; i < n; i++)
    {
        cout <<ret[i][0] << " " << ret[i][1] << endl;
    }
}
 //
// Created by yuanhao on 2019-8-30.
//
#include <iostream>
using namespace std;
// 可以用两个栈分两次做,这样只能过75%数据,
// 如果用一次循环,使用stl的stack<pair<int,int>>,可以过95%,
// 要想过100%,还得自己手写栈提高速度,而且不要用pair,对象多了也会耗时间。。。
// 没办法,为了考察出两倍的时间差异,这道题对时间卡得比较死
int main() {
    int n = 0;
    cin >> n;
    int numbers[n];
    int l_res[n];
    int r_res[n];
    for (int i = 0; i < n; ++i) {
        cin >> numbers[i];
    }
    int stack[n * 2]; // 栈,保存数字下标和数字,两个元素为一个帧
    int top = 0; //栈顶指针
    for (int i = 0; i < n; ++i) {
        while (top != 0 && numbers[i] < stack[top - 1]) {
            r_res[stack[top - 2]] = i;
            top -= 2;
        }
        if (top == 0) {
            l_res[i] = -1;
        } else {
            if (numbers[i] == stack[top - 1]) {
                l_res[i] = l_res[stack[top - 2]];
            } else {
                l_res[i] = stack[top - 2];
            }
        }
        stack[top++] = i;
        stack[top++] = numbers[i];
    }
    while (top != 0) {
        r_res[stack[top - 2]] = -1;
        top -= 2;
    }
    for (int i = 0; i < n; ++i) {
        printf("%d %d\n", l_res[i], r_res[i]);
    }
    return 0;
} 头条一面没写出来,现在运行不出来
#include 
(849)#include 
#include 
using namespace std;
int main()
{
    int n = 0;
    cin >> n;
        vector nums(n);
        for (int i = 0; i < n; i++)
        {
            cin >> nums[i];
        }
        vector prevs(n, -1);
        vector nexts(n, -1);
        stack s;
        s.push(0);
        for (int i = 1; i < nums.size(); i++)
        {
            if (nums[s.top()] <= nums[i])
            {
                prevs[i] = s.top();
                s.push(i);
            }
            else
            {
                while (!s.empty() && nums[s.top()] > nums[i])
                {
                    s.pop();
                }
                if (!s.empty())
                {
                    prevs[i] = s.top();
                }
                s.push(i);
            }
        }
        s.push(n - 1);
        for (int i = n - 2; i >= 0; i--)
        {
            if (nums[i] < nums[s.top()])
            {
                s.push(i);
            }
            else
            {
                nexts[i] = s.top();
            }
        }
        for (int i = 0; i < n; i++)
        {
            cout << prevs[i] << " " << nexts[i] << endl;
        }
}
                                                                                    #include <bits/stdc++.h>
using namespace std;
struct node
{
    int left, right;
};
int main(int argc, char const *argv[])
{
    int n;
    cin >> n;
    vector<int> a;
    for (int i = 0; i < n; i++)
    {
        int t;
        cin >> t;
        a.push_back(t);
    }
    vector<node> nn(n);
    for (int i = 0; i < n; i++)
    {
        nn[i].left = -1;
        nn[i].right = -1;
    }
    nn[0].left = -1;
    for (int kk = 1; kk < a.size(); kk++)
    {
        if (a[0] > a[kk])
        {
            nn[0].right = kk;
            break;
        }
    }
    nn[a.size() - 1].right = -1;
    for (int kk = a.size() - 2; kk >= 0; kk--)
    {
        if (a[a.size() - 1] > a[kk])
        {
            nn[a.size() - 1].left = kk;
            break;
        }
    }
    for (int i = 1; i < a.size() - 1; i++)
    {
        for (int jj = i - 1; jj >= 0; jj--) /*left*/
        {
            if (a[jj] < a[i])
            {
                nn[i].left = jj;
                break;
            }
        }
        for (int kkk = i + 1; kkk < a.size(); kkk++)/*right*/
        {
            if (a[i] > a[kkk])
            {
                nn[i].right = kkk;
                break;
            }
        }
    }
    for (int i = 0; i < n; i++)
    {
        cout << nn[i].left << " " << nn[i].right << endl;
    }
    return 0;
}
  75% 纯数组写的
                                                                                    #include <vector>
#include <iostream>
#include <stack>
#include <stdio.h>
using namespace std;
int main() {
	int n;
	scanf("%d", &n);
	vector<int> datas(n);
	vector<int> Lres(n, -1);
	vector<int> Rres(n, -1);
	stack<int> arrdeq;
	for (int i = 0; i < n; i++) {
		scanf("%d", &datas[i]);
		while (!arrdeq.empty() && datas[arrdeq.top()] >= datas[i]) {
			arrdeq.pop();
		}
		if (!arrdeq.empty()) {
			Lres[i] = arrdeq.top();
		}
		arrdeq.push(i);
	}
	stack<int> arrdeq2;
	for (int i = n - 1; i >= 0; i--) {
		while (!arrdeq2.empty() && datas[arrdeq2.top()] >= datas[i]) {
			arrdeq2.pop();
		}
		if (!arrdeq2.empty()) {
			Rres[i] = arrdeq2.top();
		}
		arrdeq2.push(i);
	}
	for (int i = 0; i < n; i++) {
		printf("%d %d\n", Lres[i], Rres[i]);
	}
	return 0;
} import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner  sc=new Scanner(System.in);
        int n=sc.nextInt();
        int[] arr=new int[n];
        int[][] res=new int[n][2];
        Deque<Integer> stack=new ArrayDeque<>();
        for(int i=0;i<n;i++){
            int tmp=sc.nextInt();
            arr[i]=tmp;
            while(!stack.isEmpty()&&arr[stack.peek()]>=tmp){
                stack.pop();
            }
            if(stack.isEmpty())
                 res[i][0]=-1;
            else
                res[i][0]=stack.peek();
            stack.push(i);
        }
        stack.clear();
        for(int i=arr.length-1;i>=0;i--){
             while(!stack.isEmpty()&&arr[stack.peek()]>=arr[i]){
                stack.pop();
            }
            if(stack.isEmpty())
                 res[i][1]=-1;
            else
                res[i][1]=stack.peek();
            stack.push(i);
        }
        StringBuilder sb=new StringBuilder();
        for(int[] t:res){
            sb.append(t[0]).append(" ").append(t[1]).append("\n");
        }
        System.out.println(sb.toString());
        sc.close();
    }
} #include <bits/stdc++.h>
using namespace std;
int main(){
    int n;
    cin>>n;
    int a[n], l[n], r[n];
    stack<int> S;
    for(int i=0;i<n;i++){
        cin>>a[i];
        l[i] = r[i] = -1;
    }
    for(int i=0;i<n;){
        if(S.empty()){
            S.push(i++);
        }else if(a[i]>=a[S.top()]){
            if(a[i] == a[S.top()])
                l[i] = l[S.top()];
            else
                l[i] = S.top();
            S.push(i++);
        }else{
            r[S.top()] = i;
            S.pop();
        }
    }
    for(int i=0;i<n;i++)
        printf("%d %d\n", l[i], r[i]);
    return 0;
} #include <stdio.h>
#include<malloc.h>
int main()
{
    int n,*arr;
    scanf("%d",&n);
    arr=(int *)malloc(sizeof(int)*n);
    for(int a=0;a<n;a++)
    {
        scanf("%d",arr+a);
    }
    for(int a=0,e=0,b;a<n;a++)
    {e=0;
        for( b=a-1;b>=0;b--)
        {
            if(*(arr+b)<*(arr+a))
            {
                printf("%d ",b);
                e=1;
                break;
            }
        }
        if(!e)
        {
            printf("-1 ");
        }
        e=0;
        for(b=a+1;b<n;b++)
        {
            if(*(arr+b)<*(arr+a))
            {
                printf("%d",b);
                e=1;
                break; 
            }
        }
        if(!e)
        {
            printf("-1");
        }
    
        printf("\n");
}} import java.util.Arrays;
import java.util.Scanner;
import java.util.Stack;
/**
 * 给定一个可能含有重复值的数组 arr,
 * 找到每一个 i 位置左边和右边离 i 位置最近且值比 arr[i] 小的位置。返回所有位置相应的信息。
 * @author zhuqiu
 * @date 2020/3/25
 */
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int len = in.nextInt();
        int[] arr = new int[len];
        for (int i = 0; i < len; i++) {
            arr[i] = in.nextInt();
        }
        int[] left = new int[len];
        int[] right = new int[len];
        Arrays.fill(right, -1);
        Arrays.fill(left, -1);
        method(len, left, right, arr);
        for (int i = 0; i < len; i++) {
            System.out.printf("%d %d\n", left[i], right[i]);
        }
    }
    public static void method(int len, int[] left, int[] right, int[] arr){
        Stack<Integer> stack = new Stack();
        for (int i = 0; i < len; i++) {
            while (!stack.isEmpty() && arr[stack.peek()] > arr[i]){
                right[stack.pop()] = i;
            }
            int top = stack.isEmpty()?-1:stack.peek();
            if (stack.isEmpty()){
            } else if (arr[stack.peek()] != arr[i]){
                left[i] = top;
            } else{
                left[i] = left[top];
            }
            stack.push(i);
        }
    }
}
 只有75%,也不知道怎么优化了
                                                                                    a=input() b=[int(i) for i in input().split()] def left(c): n = c - 1 for j in reversed(b[:c]): if b[c]>j: return n n-=1 return -1 def right(c): n=c+1 for i in b[c+1:]: if b[c]>i: return n n+=1 return -1 i=0 while i<len(b): cen=b[i] if i==0: le=-1 r=right(i) print(le,r) elif i==len(b)-1: le=left(i) r=-1 print(le,r) else: le=left(i) r=right(i) print(le,r) i+=1
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;
void async function () {
    const n = await readline();
    const arr = (await readline()).split(' ').map((item) => Number(item));
    const stack = [];
    const res = new Array(n);
    for (let i = 0; i < n; i++) {
        const cur = arr[i];
        while (stack.length && arr[stack[stack.length - 1]] >= cur) {
            const top = stack.pop();
            res[top] = [stack.length ? stack[stack.length - 1] : -1, i];
        }
        stack.push(i);
    }
    while (stack.length) {
        const top = stack.pop();
        res[top] = [stack.length ? stack[stack.length - 1] : -1, -1];
    }
    for (let i = n - 1; i >= 0; i--) {
        const cur = arr[i];
        let right = res[i][1];
        if (right > 0 && arr[right] === cur) {
            right = res[right][1];
        }
        res[i][1] = right;
    }
    console.log(res.map((item) => item.join(' ')).join('\n'));
}()
 这是一道单调站的模板题目,这是最快的C++的模板,其他语言用这个算法一样
#include <iostream>
#include <cstring>
using namespace std;
const int N = 1e6 + 10;
int stk[N];//手写的栈,常数时间比STL的栈要好
int tt = 0;
int arr[N];
int L[N], R[N]; //左侧第一个比自己小的数字和右侧第一个比自己小的数字
int main() {
    int n;
    cin >> n;
    for (int i = 0; i < n; i++) {
        scanf("%d",&arr[i]);
    }
    for (int i = 0; i < n; i++) {
        while (tt && arr[i] <= arr[stk[tt]]) {//当栈不空的时候,并且栈顶不是严格单调的时候弹出元素
            R[stk[tt]] = i;
            tt--;
        }
        if (tt)L[i] = stk[tt];//记录左侧答案
        else L[i] = -1;
        stk[++tt] = i;//每一个元素都要进栈
    }
    while (tt) { //清算阶段,因为用
        int t = stk[tt--];
        R[t] = -1;
    }
    for (int i = n-1; i >= 0 ; i--) {//处理相同的情况
        if(arr[R[i]] == arr[i]) R[i] = R[R[i]];
    }
 
    for (int i = 0; i < n; i++) {//输出答案,这里输入输出微末比较大,使用C风格的函数会比CIN,COUT快10倍
        if (L[i] != -1)
            printf("%d ",L[i]);
        else
            printf("-1 ");
        if (R[i] != -1)
            printf("%d \n",R[i]);
        else
            printf("-1 \n");
            
    }
    return 0;
} // 两次遍历
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.StreamTokenizer;
import java.util.Deque;
import java.util.ArrayDeque;
public class Main {
    private static StreamTokenizer st = new StreamTokenizer(
        new BufferedReader(new InputStreamReader(System.in))
    );
    private static int nextInt() {
        try {
            st.nextToken();
            return (int) st.nval;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    private static int[][] findNearestLessThan(int[] nums) {
        int n = nums.length;
        int[][] res = new int[n][2];
        Deque<Integer> stack = new ArrayDeque<>();
        for (int i = 0; i < n; ++i) {
            while (!stack.isEmpty() && nums[i] <= nums[stack.peek()]) {
                stack.pop();
            }
            res[i][0] = stack.isEmpty() ? -1 : stack.peek();
            stack.push(i);
        }
        stack.clear();
        for (int i = n - 1; i >= 0; --i) {
            while (!stack.isEmpty() && nums[i] <= nums[stack.peek()]) {
                stack.pop();
            }
            res[i][1] = stack.isEmpty() ? -1 : stack.peek();
            stack.push(i);
        }
        return res;
    }
    public static void main(String[] args) {
        int n = nextInt();
        int[] arr = new int[n];
        for (int i = 0; i < n; ++i) {
            arr[i] = nextInt();
        }
        int[][] res = findNearestLessThan(arr);
        StringBuilder sb = new StringBuilder();
        for (int[] pair : res) {
            sb.append(pair[0] + " " + pair[1] + "\n");
        }
        System.out.println(sb);
    }
}
// 一次遍历
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.StreamTokenizer;
import java.util.Deque;
import java.util.ArrayDeque;
public class Main {
    private static StreamTokenizer st = new StreamTokenizer(
        new BufferedReader(new InputStreamReader(System.in))
    );
    private static int nextInt() {
        try {
            st.nextToken();
            return (int) st.nval;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    private static int[][] findNearestLessThan(int[] nums) {
        int n = nums.length;
        int[][] res = new int[n][2];
        Deque<Integer> stack = new ArrayDeque<>();
        for (int i = 0; i <= n; ++i) {
            while (!stack.isEmpty() && (i == n || nums[i] < nums[stack.peek()])) {
                res[stack.pop()][1] = i < n ? i : -1;
            }
            if (i == n) {
                break;
            }
            if (stack.isEmpty()) {
                res[i][0] = -1;
            } else {
                int peek = stack.peek();
                res[i][0] = (nums[i] == nums[peek]) ? res[peek][0] : peek;
            }
            stack.push(i);
        }
        return res;
    }
    public static void main(String[] args) {
        int n = nextInt();
        int[] arr = new int[n];
        for (int i = 0; i < n; ++i) {
            arr[i] = nextInt();
        }
        int[][] res = findNearestLessThan(arr);
        StringBuilder sb = new StringBuilder();
        for (int[] pair : res) {
            sb.append(pair[0] + " " + pair[1] + "\n");
        }
        System.out.println(sb);
    }
}
================================================================
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.StreamTokenizer;
import java.util.Deque;
import java.util.ArrayDeque;
public class Main {
    private static StreamTokenizer st = new StreamTokenizer(
        new BufferedReader(new InputStreamReader(System.in))
    );
    private static int nextInt() {
        try {
            st.nextToken();
            return (int) st.nval;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    private static int[][] findNearestLessThan(int[] nums) {
        int n = nums.length;
        int[][] res = new int[n][2];
        Deque<Integer> stack = new ArrayDeque<>();
        for (int i = 0; i < n; ++i) {
            res[i] = new int[] {-1, -1};
        }
        for (int i = 0; i < n; ++i) {
            while (!stack.isEmpty() && nums[i] < nums[stack.peek()]) {
                res[stack.pop()][1] = i;
            }
            if (!stack.isEmpty()) {
                int peek = stack.peek();
                res[i][0] = (nums[i] == nums[peek]) ? res[peek][0] : peek;
            }
            
            stack.push(i);
        }
        return res;
    }
    public static void main(String[] args) {
        int n = nextInt();
        int[] arr = new int[n];
        for (int i = 0; i < n; ++i) {
            arr[i] = nextInt();
        }
        int[][] res = findNearestLessThan(arr);
        StringBuilder sb = new StringBuilder();
        for (int[] pair : res) {
            sb.append(pair[0] + " " + pair[1] + "\n");
        }
        System.out.println(sb);
    }
} # 用list模拟单调栈
n = int(input())
arr = [int(k) for k in input().split()]
left = [-1 for _ in range(n)]
stk = []
# 左向右
for i in range(n):
    while stk and arr[stk[-1]] >= arr[i]:
        stk.pop()
    if stk:
        left[i] = stk[-1]
    stk.append(i)
right = [-1 for _ in range(n)]
stk = []
# 右向左
for i in range(n-1, -1, -1):
    while stk and arr[stk[-1]] >= arr[i]:
        stk.pop()
    if stk:
        right[i] = stk[-1]
    stk.append(i)
for i in range(n):
    print(f"{left[i]} {right[i]}")
 public /*List<Integer[]>*/static void test(int[] arr) {
        int n = arr.length;
        int[] left = new int[n];
        left[0] = 0;
        for (int i = 1; i < n; i++) {
            if (arr[left[i - 1]] > arr[i])
                left[i] = i;
            else left[i] = left[i - 1];
        }
        int[] right = new int[n];
        right[n - 1] = n - 1;
        for (int i = n - 2; i >= 0; i--) {
            if (arr[right[i + 1]] > arr[i])
                right[i] = i;
            else right[i] = right[i + 1];
        }
        StringBuilder sb = new StringBuilder();
        int l = -1, r = 0;
        if (arr[right[1]] < arr[0]) {
            while (++r < n && arr[r] >= arr[0]) ;
        } else
            r = -1;
        sb.append("-1 ").append(r).append("\n");
//        System.out.println("-1 " + r);
        for (int i = 1; i < n - 1; i++) {
            if (arr[i] > arr[left[i - 1]]) {   // 左边存在较小的值
                if (arr[i - 1] < arr[i])
                    l = i - 1;
                else if (arr[i - 1] > arr[i]) {
                    l = i;
                    while (--l >= 0 && arr[l] >= arr[i]) ;
                }
            } else l = -1;
            if (arr[i] > arr[right[i + 1]]) {  // 右边存在较小的值
                r = i;
                while (++r < n && arr[r] >= arr[i]) ;
            } else r = -1;
//            System.out.println(l + " " + r);
            sb.append(l).append(" ").append(r).append("\n");
//            res.add(new Integer[]{l, r});
        }
        l = n - 1;
        if (arr[left[n-2]] < arr[n - 1]) {
            while (--l < n && arr[l] >= arr[n - 1]) ;
        } else
            l = -1;
        sb.append(l).append(" -1\n");
        System.out.println(sb);
    }
public static void main(String[] args) {
        Scanner s = new Scanner(System.in);
        int n = Integer.parseInt(s.nextLine().trim());
        int[] arr = new int[n];
        String[] strings = s.nextLine().trim().split(" ");
        for (int i = 0;i<n;i++){
            arr[i] = Integer.parseInt(strings[i]);
        }
        Main.tets(arr);
    }
 中心拓展
                                                                                    import java.io.*;
import java.util.Arrays;
import java.util.Stack;
public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));
        int n = Integer.parseInt(reader.readLine());
        int[] arr = Arrays.stream(reader.readLine().split(" ")).mapToInt(Integer::parseInt).toArray();
        int[] left = new int[n];
        int[] right = new int[n];
        /**
         * 单调递增栈
         */
        Stack<Integer> stack = new Stack<>();
        for (int i = 0; i < arr.length; i++) {
            while (!stack.isEmpty() && arr[stack.peek()] > arr[i]) {
                right[stack.pop()] = i;
            }
            left[i] = stack.isEmpty() ? -1 : (arr[stack.peek()] == arr[i] ? left[stack.peek()] : stack.peek());
            stack.push(i);
        }
        while (!stack.isEmpty()) {
            right[stack.pop()] = -1;
        }
        for (int i = 0; i < n; ++i) {
            writer.write(left[i] + " " + right[i]);
            writer.newLine();
        }
        writer.flush();
    }
} #include <iostream>
#include <vector>
#include <stack>
using namespace std;
int main()
{
	int size;
    scanf("%d", &size);
	vector<int> arr(size);
    vector<int> ans1(size,-1);
    vector<int> ans2(size,-1);
	stack<int> s;
	stack<int> s1;
	for (int i = 0; i < size; i++)
    {
        scanf("%d", &arr[i]);
        while (!s.empty() && arr[s.top()] >= arr[i])
		{
			s.pop();
		}
		if (!s.empty()) ans1[i] = s.top();
		s.push(i);
    }
	for (int i = size - 1; i >= 0; i--)
	{
		while (!s1.empty() && arr[s1.top()] >= arr[i])
		{
			s1.pop();
		}
		if (!s1.empty()) ans2[i] = s1.top();
		s1.push(i);
	}
	
    for (int i = 0 ; i < size; i++)
    {
        printf("%d %d\n", ans1[i], ans2[i]);
    }
	return 0;
}