read(模拟)

时间限制: 1 Sec 内存限制: 128 MB
[提交] [状态]
题目描述
Carol是一个爱学习的小朋友,他最近在读一本书,这本书的某些页十分晦涩难懂,需要阅读完另一页的内容才能完全理解。
而有些页则比较通俗易懂,阅读完当前页即可理解。
Carol是一个喜欢钻研的小朋友,他每天都会从这本书中页数最小的从未读过的一页开始读,读到完全理解这一页的内容为止。
例如对于当Carol某一天要读这本书的第a页时,这一页要求读完第b页才能理解,于是Carol又要去读第b页,而第b页要求读完第c页才能理解,于是Carol又要去读第c页,而第c页不需要读别的页就可以理解,或是需要读的页在之前已经读过了,最终Carol这一天读了a,b,c这三页内容。
Carol想知道自己需要花多少天才能读完这本书。
输入
第一行一个整数n,表示这本书有n页
第二行有n个正整数a1,a2,…,an,其中ai表示要读完第i页的内容要先读完第ai页的内容。(ai≥i)
输出
一个正整数,表示读完这本书需要的时间。
样例输入 Copy
【样例1】

6
1 3 3 5 6 6

【样例2】

10
3 4 3 4 8 7 8 10 10 10

样例输出 Copy
【样例1】

3

【样例2】

5

提示
样例1解释:
第一天Carol读了第一页,不需要再阅读其他页。
第二天Carol读了第二页,第二页要求读完第三页,于是他又读了第三页。
第三天Carol读了第四页,第四页要求读完第五页,第五页又要求读完第六页,于是他把这些页都读了。

样例2解释:
第一天Carol读了第1, 3页
第二天Carol读了第2, 4页
第三天Carol读了第5, 8, 10页
第四天Carol读了第6, 7页
第五天Carol读了第9页

对于20%的数据,ai=i
对于另外20%的数据,ai = min(i + 2, n)
对于所有数据,1≤n≤100000
结合题意和样例,思路应该不难想,就是根据要读第i页的内容确定的要先读完的第ai页内容一步步转移,直到没有书可读或要读的页数与先读的页数相同。
模拟一下样例2:

i a[i]
1  3
2  4
3  3
4  4
5  8
6  7
7  8
8  10
9  10
10 10

读第1页,要先读第a[1]=3页;读第3页,要先读第a[3]=3页,3=3,此时为第一天读的页数;
从最小的未读的页开始,读第2页,要先读第a[2]=4页;读第4页,要先读第a[4]=4页,4=4,此时为第二天读的页数;
从最小的未读的页开始,读第5页,要先读第a[5]=8页;读第8页,要先读第a[8]=10页;读第10页,要先读第a[10]=10页,10=10,此时为第三天读的页数;
从最小的未读的页开始,读第6页,要先读第a[6]=7页;读第7页,要先读第a[7]=8页,由于第8页已读,故不再往后寻找,此时为第四天读的页数;
从最小的未读的页开始,读第9页,要先读第a[9]=10页,由于第10页已读,故不再往后寻找,此时为第五天读的页数;
至此所有的页均已读,遍历结束。

#include<stdio.h>
int a[100005];
int vis[100005]={0};
int main()
{
    int n,i,j,day=0;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    for(i=1;i<=n;i++)
    {
        if(vis[i]==0)//第一个未读的页
        {
            j=i;//从第i页开始往后寻找
            while(j!=a[j])//一般情况下退出循环的条件是要读的页与要先读完的页相等
            {
                vis[j]=1;//标记为已读
                j=a[j];//转移
                if(vis[j]==1)break;//如果转移后的页已读,则退出循环,不再往后寻找
            }
            vis[j]=1;//要读的页与要先读完的页相等的标为已读
            day++;//天数+1
        }
    }
    printf("%d",day);
    return 0;
}
/**************************************************************
    Language: C++
    Result: 正确
    Time:23 ms
    Memory:1900 kb
****************************************************************/
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值