P2058 海港

在这里插入图片描述
在这里插入图片描述
说明/提示
【样例解释1】

第一艘船在第11秒到达海港,最近2424小时到达的船是第一艘船,共有44个乘客, 分别是来自国家4,1,2,24,1,2,2,共来自33个不同的国家;

第二艘船在第22秒到达海港,最近2424小时到达的船是第一艘船和第二艘船,共有 4 + 2 = 64+2=6个乘客,分别是来自国家4,1,2,2,2,34,1,2,2,2,3,共来自44个不同的国家;

第三艘船在第1010秒到达海港,最近2424小时到达的船是第一艘船、第二艘船和第 三艘船,共有4+ 2+1=74+2+1=7个乘客,分别是来自国家4,1,2,2,2,3,34,1,2,2,2,3,3,共来自4$$个不同 的国家。

【样例解释2】

第一艘船在第11秒到达海港,最近2424小时到达的船是第一艘船,共有44个乘客,分别是来自国家1,2,2,31,2,2,3,共来自33个不同的国家。

第二艘船在第33秒到达海港,最近2424小时到达的船是第一艘船和第二艘船,共有4+2=64+2=6个乘客,分别是来自国家1,2,2,3,2,31,2,2,3,2,3,共来自33个不同的国家。

第三艘船在第8640186401秒到达海港,最近2424小时到达的船是第二艘船和第三艘船,共有2+2=42+2=4个乘客,分别是来自国家2,3,3,42,3,3,4,共来自33个不同的国家。

第四艘船在第8640286402秒到达海港,最近2424小时到达的船是第二艘船、第三艘船和第四艘船,共有2+2+1=52+2+1=5个乘客,分别是来自国家2,3,3,4,52,3,3,4,5,共来自44个不同的国家。

【数据范围】
在这里插入图片描述

这道题,我真的。。。。快做吐了。最开始我是这样写的

#include<iostream>
#include <map>
#include <vector>
#include <cstring>
using namespace std;
#define Max 300001
struct Node
{
    int time;//到达时间
    int g;//国籍
};
vector<Node> res;
int M[Max]; //判断国籍a[i]是否被使用过
    int main()
    {

        Node node;
        int n,t,k,x;
        cin>>n;
        int cnt=0;
        for(int i=1;i<=n;i++)
        {
            cnt=0;
            cin>>t>>k;//时间递增
            memset(M,0, sizeof(M));
            for(int j=1;j<=k;j++) //先判断输入的
            {
                cin>>x;//输入 i号船的国籍成员
                node.time=t;
                node.g=x;
                res.push_back(node);
                if(M[x]==0)
                {
                    cnt++;
                    M[x]=1;
                }
            }
            vector<Node>::iterator beg=res.begin();
            vector<Node>::iterator end=res.end()-(k+1);
            while(beg<=end)
            {
                if(M[beg->g]==0&&t-beg->time<86400)
                {
                    M[beg->g]=1;
                    cnt++;
                }
                if(M[end->g]==0&&t-end->time<86400)
                {
                    M[end->g]=1;
                    cnt++;
                }
                if(t-end->time>=86400)
                {
                    break;
                }
                beg++;
                end--;
            }
            cout<<cnt<<endl;
        }
        return 0;
    }

最开始是单指针,后来改写双指针,结局一样的悲惨,两个都T掉了6个点,我想尽一切办法来优化,还是不能全部AC,始终有6个点T掉,70分!!!!… 后来看到了算法标签,正解是队列

算法的思路:

我们先创造一个结构体,结构体里面存储个人的到达时间和国籍,不要存储整艘船的,那样写起来太复杂了,所以我们搞一个记录个人的信息(到达时间 and 国籍),除此之外,我们还要搞一个记录国籍人数的数组,int a[MAX]

接下来就是主题了,我们首先输入当前时间的所有人员,将当前时间船上所有成员信息保存在结构体里面并入队,假设此时船上的这个成员的国籍是i,我们使得a[i]++,并检查一下a[i]++之后的a[i]是否等于1,如果等于1,那么使得记录“当前船上和之前24小时船上不同国籍人员”的变量 cnt+1

这是输入部分,接下来我们还要减去相对当前而言之前超过24小时的国籍人员,我们从队列头中检查一下元素,就是队头的元素,我们检查一下当前时间–队头元素的时间是否大于等于86400,如果大于86400,我们弹出这个元素并将我们上面那个 a[队头时间]-- , 如果此时a[队头时间]==0,那么我们就将cnt–,如果当前时间t-队头时间小于86400,那么我们跳出循环

下面是AC代码~

#include<iostream>
#include <queue>
#include <cstring>
using namespace std;
#define Max 300001
struct Node
{
    int time;//到达时间
    int g;//国籍
};
vector<Node> res;
int M[Max]; //存储国籍的数量
int main()
{

    memset(M,0, sizeof(M));
    Node node;
    queue<Node> f;
    int n,t,k,x;
    cin>>n;
    int cnt=0;
    for(int i=1;i<=n;i++) {
        cin>>t>>k;
        node.time=t;
        for(int j=1;j<=k;j++)
        {
            cin>>node.g;
            f.push(node);
            M[node.g]++;
            if(M[node.g]==1)
            {
                cnt++;
            }
        }
        while(!f.empty())
        {
            Node temp=f.front();
            if(t-temp.time>=86400)
            {
                M[temp.g]--;
                if(M[temp.g]==0)
                {
                    cnt--;
                }
                f.pop();
            }
            else
            {
                break;
            }
        }
        cout<<cnt<<endl;
    }
    return 0;
}

上面的算法思想有些不好理解,还是举两个例子

3
1 4 4 1 2 2
2 2 2 3
10 1 3

比如样例的这个数据
输入部分: M[4]=1,M[1]=2,M[2]=2;
cnt=3
队头时间不满足条件,跳出来

输入部分:M[2]=3,M[3]=1
cnt = 4
队头时间不满足条件,跳出来

输入部分:,M[3]=2
cnt=4
队头时间不满足条件,跳出来

上面好像也不能体现算法,看到样例2
4
1 4 1 2 2 3
3 2 2 3
86401 2 3 4
86402 1 5

输入部分:M[1]=1,M[2]=2,M[3]=1
cnt=3
队头时间不满足条件,跳出来

输入部分:M[2]=3,M[3]=2
cnt=4
队头时间不满足条件,跳出来

输入部分:M[3]=3,M[4]=1
cnt=4
第一艘船的队头时间满足,元素全部弹出,并且:M[2]=M[2]-2=1,M[3]=M[3]-1=2,M[1]=M[1]-1=0,cnt=cnt-1=3

现在的M[2]=1,M[3]=2,M[1]=0,M[4]=1

输入部分:M[5]=1
cnt=3
队头时间是船二的到达时间,条件不满则。跳出来
cnt=3

怎么样是不是很巧妙算法,和第一种比较起来,第一种的算法思路更加清晰,但是效率有点慢了,甚至还T掉了5个点,下面这种算法虽然比上面的稍微难一点理解,但是可以全部AC,40ms变成了4ms,剪纸不要太爽。祝大家早日AC~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值