1948. 英雄辈出题解析

题目描述

当今世界英雄人物层出不穷,分分钟出一个英雄人物。Lester记录着每个英雄的出场顺序,一共有n个英雄,Lester为他们打分从1到n,第i个英雄打分为x[i],分数各不相同,分数越高实力越强。已知对这n个英雄的依次打分序列 {x[i]} 形成了1到n的一个排列。这n个英雄中的每一个都要知道一件事情:在自己之后最早出现比自己强的人是几号?如果没有比自己强的就算做n+1号。

输入输出格式

输入格式

输入文件heroes.in
输入第一行为正整数n,不超过200000。第二行为n个正整数,由空格隔开,是1到n的排列。

输出格式

输出文件heroes.out
输出一行包含n各正整数。

输入输出样例

输入样例#1:

4
2 1 4 3

输出样例#1:

3 3 5 5
【说明】2后面第一个比它大的数是4(第3个数);1后面第一个比它大的数是4(第3个数);4后面没有比它大的数,输出5;3后面没有比它大的数,输出5。

输入样例#2:

3
1 2 3

输出样例#2:

2 3 4
【说明】1后面第一个比它大的数是2(第2个数);2后面第一个比它大的数是3(第3个数);3后面没有比它大的数,输出4。

解析

0.暴力枚举

复杂度O(N 2 )
对于随机数据挺快的
因为很快就可能跳出循环

从左到右查看每个位置i                                                                
        从i+1开始从左到右
        依次查看每一个位置j
                如果第一次发现x[j]>x[i]
                        ans[i]=j
                        对于i号位置答案就是j
                        跳出内层循环 

0.1代码来咯~~~~

    int n;
    cin>>n;
    for(int i=1;i<=n;i++)cin>>x[i];
    x[n+1]=n+1;
    for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n+1;j++)
            if(x[j]>x[i]){
                cout<<j<<" ";
                break;
            }

1.0建模元素分析

当输出要回答多个问题时,有两类常见问询

在线问询    一问一答
离线问询    审问犯人,微信聊天
可以看完问题
换顺序回答
做考卷做作业
此题问了n个问题,属于哪一类?

1.1离线问询+双链表删除

离线问询

可以看完问题
换顺序回答

挑选最简单的
问题是哪个

i=1  i=2  i=3  i=4  1=5  1=6

6       4     2   1      3       5

得1分的人,他的答案就是此时他贴身右边邻居位置

得1分的人确定后,得分2的人能否确定呢?

将得1分的人删除后        他的答案就是此时他贴身
分析得分2的人                右边邻居位置

将得2分的人删除后        他的答案就是此时他贴身
分析得分3的人                右边邻居位置

......        ......        ......        ......        ......        ......

1.2代码来咯

    for(int i=1;i<=n;i++){
        cin>>x[i];
        p[x[i]]=i;
        nxt[i]=i+1;
        pre[i]=i-1;
    }
    for(int i=1;i<=n;i++){
        ans[p[i]]=nxt[p[i]];
        nxt[pre[p[i]]]=nxt[p[i]];
        pre[nxt[p[i]]]=pre[p[i]];
    }
    for(int i=1;i<=n;i++)cout<<ans[i]<<" ";

1.3代码简化

    for(int i=1;i<=n;i++){
        cin>>x[i];
        p[x[i]]=i;
        nxt[i]=i+1;
        pre[i]=i-1;
    }
    for(int i=1;i<=n;i++){
        nxt[pre[p[i]]]=nxt[p[i]];
        pre[nxt[p[i]]]=pre[p[i]];
    }
    for(int i=1;i<=n;i++)cout<<nxt[i]<<" ";

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值