1141. [湖北2011寒假] 求M数
★ 输入文件:allm.in
输出文件:
allm.out
简单对比
时间限制:10 s 内存限制:128 MB
【题目描述】
n 个数排成一排。一个数的M 数是指的在这个数的左边且比它小的数中最靠近它(即
最靠右)的那个数。依次给出这n 个数,请求出所有这n 个数相对应的M 数。
【输入格式】
从文件allm.in 中读入数据。
数据的第一行是一个正整数n,表示一共有多少个数。
第二行有n 个用空格隔开的正整数,它们从左至右给出了数列中的n 个数。这些数保证
小于2^31。
【输出格式】
输出一行用空格隔开的n 个数到文件allm.out。
这些数对应输入数据中的数的M 数。如果输入中某个数没有M 数(即它左边的数都不
比它小),请输出0。
【样例输入】
7 3 1 2 7 6 7 4
【样例输出】
0 0 1 2 2 6 2
【提示】
对于100%的数据,有n<=1000000.
可以用线段树,但是用记忆化搜索实现比较简单点。 按题意开一个数组记录每个数左边最接近当前这个数的位置。下次搜索的时候直接跳转。
#include<cstdio>
using namespace std;
const int maxn = 1000000+100;
int a[maxn],pos[maxn],ans[maxn];
int main(){
freopen("allm.in","r",stdin);
freopen("allm.out","w",stdout);
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++) pos[i]=1;
for(int i=1;i<=n;i++){
int flag=0,index;
for(int j=i-1;j>=1;j=pos[j]){
if(a[j]<a[i]){
flag=1; index=j;
break;
}
}
if(flag){
pos[i]=index;
ans[i]=a[index];
}
else{
pos[i]=0;
}
}
for(int i=1;i<=n;i++) printf("%d ",ans[i]);
return 0;
}