hdu~3410(单调队列)

单调队列就是队列中的元素是单调递增或递减的。比如把 5 2 3 1 4 入队:

减:、、、、、、、、、、、增:

5 、、、、、、、、、、、、5

5 2 、、、、、、、、、、、

5 3 、、、、、、、、、、、2 3

5 3 1、、、、、、、、 、、1

5 4 、、、、、、、、、、、1 4


这个还是好理解的,但是,我们得会用单调队列这一特性去解决题目,抽象出题目中有类似的操作。


Passing the Message

题意:

给你n个数a[1~n],让你输出两行数据,每行n个数。

1.对于第一行的n个数l[1~n]:把第k个数记为x,

      x就是 在a[k]左边第一个比a[k]大的数  到  a[k]之间的数中(不包括这两个),最大的那个数的下标。

      比如:2 5 1 2 3 4

      对于 l[6],左边比他小的是 a[3]=1 a[4]=2 a[5]=3 ,a[5] 最大,所以l[6]=5;

2.对于第二行r[1~n]就是从右边开始,其他定义和第一行一样。


测试数据 :5 2 4 3 1

a[1]=5左边比他的的是a[0]a[0]到a[1]之间没有数l[1]=0;

  a[2]=2左边比他的的是a[1]=5,a[1]到a[2]之间没有数,l[2]=0;

a[3]=4左边比他大的数a[1]=5,在a[1]<

a[4]=3左边比他的的是a[3]=4,a[3]到a[4]之间没有数,l[4]=0;

 a[5]=1左边比他的的是a[4]=3,a[4]到a[5]之间没有数,l[5]=0;

具体的不说了,上代码,看注释呗:

#include 
#include 
#define INF 0xfffffff

using namespace std;
int main()
{
    int t,ti;
    int l[50005],r[50005],a[50005];
    scanf("%d",&t);
    for(int ti=1;ti<=t;ti++){
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        deque q;
        for(int i=1;i<=n;i++) //左边开始
        {
            int sign=1,last=0;
            while(!q.empty() && a[q.back()] a[i]
            else l[i]=last;    //否则,最后弹出的一个元素   必是   在比a[i]小的元素中,最大的那个
            q.push_back(i);
        }

        for(int i=n;i>=1;i--)   //右边开始,同上
        {
            int sign=1,last=0;
            while(!q.empty() && a[q.back()]







你可能感兴趣的:(acm)