您的位置:首页 > 其它

hdu~3410(单调队列)

2015-04-21 11:07 127 查看
单调队列就是队列中的元素是单调递增或递减的。比如把 5 2 3 1 4 入队:

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

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

5 2 、、、、、、、、、、、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[3]之间,有一个a[2],所以l[3]=2;

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 <stdio.h>
#include <deque>
#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 <int >q;
for(int i=1;i<=n;i++) //左边开始
{
int sign=1,last=0;
while(!q.empty() && a[q.back()]<a[i]) { //维护单调队列,对头的元素最大
sign=0;
last=q.back();
q.pop_back();
}
if(sign) l[i]=0;   //若未弹出一个元素,则a[i-1] > 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()]<a[i]) {
sign=0;
last=q.back();
q.pop_back();
}
if(sign) r[i]=0;
else r[i]=last;
q.push_back(i);
}

printf("Case %d:\n",ti);
for(int i=1;i<=n;i++)
printf("%d %d\n",l[i],r[i]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: