您的位置:首页 > 其它

who is in front of me 解题报告

2014-04-05 08:35 411 查看
题目描述:N(1<=N<=50005)个学生站成一个纵队,每个人只能看到前面身高比他高(严格大于)的人

求所有人中能看到的最大人数

分析:对于某个人A,设前面第一个身高比他高的人是B。如果B不存在,那么A看到0个人。若B存在,那么A既能看到B,也能看到B所能看到的人(PS:题意是每个人只能看到身高严格大于自己的人,身高与自己相同的人视为看不见)。

状态表示:F(x)表示x能看到的人数

转移方程:F(A)=F(B)+1

怎么才能很快找到A前面第一个比他高的人是谁?对于每个人x,记录他前面第一个比他高的人legt[x]。对于每个人A,我们比较A和A-1的高矮,如果A-1比A高,那么A-1自然是第一个比他高的人。否则我们寻找第一个比A-1高的人,也就是left[A-1],因为在A-1与left[A-1]之间的所有人,身高都比A-1矮,他们也自然不可能比A高。比较A与left[A-1]的高矮,如果不行再找left[left[A-1]]...,直到找到比A高的人,或者发现没有一个人比A高。然后可以用dp求解了。

计算left的代码如下,h为每个人的高度:

for(int i=0;i<N;i++){

int j;

for(j=i-1;j>=0&&h[j]<=h[i];j=left[j]) ;

left[i]=j;

}

#include<cstdio>
int T,n,h[50005],num[50005],left[50005];
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=0; i<n; i++)
scanf("%d",&h[i]);
int best=0;
for(int i=0; i<n; i++)
{
int j;
for(j=i-1; j>=0&&h[j]<=h[i]; j=left[j])
;
left[i]=j;
if(j==-1) num[i]=0;
else num[i]=num[j]+1;
best= best>num[i] ? best : num[i];
}
printf("%d\n",best);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: