P2058 海港

原题链接  https://www.luogu.org/problemnew/show/P2058

这道题昨天qyf大佬刚给我们讲了一下,所以今天就把它做啦!

qyf大佬的思路和我的是一样的(其实是借鉴了qyf大佬的思路),但是由于他是用的指针+动态数组来实现的,这搞得我有些懵,今天仔细一想(没看题解QwQ~)发现可以用队列来实现,所以为了记录这个思路,写了一篇队列的博客。

想看指针+动态数组实现的同学们戳这里,还送屠龙宝刀哦~  传送门

首先这是一道模拟题,思路也很简单:

1. 题目中要求有多少个不同的国籍,所以我们先开一个 nat 数组类似于桶排那样来记录第 i 个国籍有多少人;

2. 对于当前到来的船,我们可以将这艘船的所有乘客全入队(注意是乘客!),他们维护两个信息:到来的时间 t 和国籍 nation;

3. 我们要统计 ( t- 86400,ti ] ,所以我们要有一个 delete 操作将队列里所有 t <= ti - 86400 的乘客弹出队列,同时注意对应的国籍人数减一;

4. 考虑到 nat 记录的是国籍的人数,那么我们可以想到:若 nat [ i ] 从一个大于0的数减到了0,那么不就说明这个国籍就没有了?此时的国籍数kind就要 -1;同理若 nat [ i ] 从0加了一个正数,说明该国籍出现了,那么此时的国籍数kind 就要 +1;

5. 然后我们输出kind 即可;

代码如下:

#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
int read()
{
    char ch=getchar();
    int a=0,x=1;
    while(ch<'0'||ch>'9')
    {
        if(ch=='-') x=-x;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        a=(a<<3)+(a<<1)+(ch-'0');
        ch=getchar();
    }
    return a*x;
}
struct people
{
    int t,nation;
}a[100001];
queue<people> q;
int n,num,guo,kind,t[100001],vis[100001];
void delet(int tim)
{
    people f=q.front();               //因为我们是按照时间顺序来将乘客入队的,所以队首乘客的t一定最小 
    while(f.t<=tim)
    {
        q.pop();
        vis[f.nation]--;              //对应国籍人数减一 
        if(vis[f.nation]==0) kind--;  //国籍人数减到0,说明这种国籍消失,国籍数kind减一    
        f=q.front();
    }
    return ;
}
int main()
{
    n=read();                         //n艘船 
    for(int i=1;i<=n;i++)
    {
        t[i]=read();                  //这一艘船到来的时间 
        num=read();                   //乘客人数  
        for(int j=1;j<=num;j++) 
        {
            guo=read();               //所属国籍 
            if(!vis[guo]) kind++;     //如果之前这种国籍的人数为0,说明多了一种国籍 
            vis[guo]++;
            q.push((people){t[i],guo});//入队,维护时间t 和国籍nation 
        }
        delet(t[i]-86400);            //删除t[i]-86400以前的船,注意要放在入队操作之后 
        printf("%d\n",kind);          
    }
    return 0;
}

 

posted @ 2019-06-27 16:13  暗い之殇  阅读(225)  评论(0编辑  收藏  举报