爱思创 180516 海港

180516 海港

思路

我们先看题
有用的题目描述分为两部分:

对于第 \(i\) 艘到达的船,他记录了这艘船到达的时间 \(t_i\)(单位:秒),船上的乘客数 \(k_i\),以及每名乘客的国籍 \(x_{i,1}, x_{i,2},\dots,x_{i,k}\)

肯定要用结构体,但存什么呢?
船? 不行,国籍得建数组,爆空间
那只能存人了。要存两个量:

  1. t:代表到达时间
  2. x:代表国籍
struct Node
{
    int t, x;
};

计算出以每一艘船到达时间为止的 24 小时(24 小时 = 86400 秒)内所有乘船到达的乘客来自多少个不同的国家。
形式化地讲,你需要计算 \(n\) 条信息。对于输出的第 \(i\) 条信息,你需要统计满足 \(t_i-86400<t_p \le t_i\) 的船只 \(p\),在所有的 \(x_{p,j}\) 中,总共有多少个不同的数。

正常的模拟肯定不行,会爆时间。那怎样优化呢?

我们可以用尺取法来优化,可以用队列模拟双指针,队首是左端点,队尾是右端点。需要再建一个桶 cnt[],cnt[i]代表国籍为i的人数
边输入边操作

输入时:

cnt[x] ++;//国籍为x的人加一
if(cnt[x] == 1) ans ++;//如果国籍x有了人,则国籍总类别加一
q.push(Node{t, x});//入队

每一次输入完成后:

while(!q.empty() && q.front().t + 86400 <= t)//如果队不空并且队首(最先到达的)的时间不符合24小时条件
{
    cnt[q.front().x] --;//国籍为x的人减一
    if(cnt[q.front().x] == 0) ans --;//如果国籍为x的人数为零,则少一种国籍数
    q.pop();//出队
}
cout << ans << endl;//输出符合条件的国籍数量

完整代码

#include<bits/stdc++.h>
using namespace std;
int cnt[100005], n, k, t, x;
struct Node
{
    int t, x;
};
queue<Node> q;//建队列,类型为建好的 Node
int main()
{
    int ans = 0;//国家种类数
    cin >> n;
    for(int i = 1; i <= n; i ++)
    {
        cin >> t >> k;//输入时间、人数
        for(int j = 1; j <= k; j ++)
        {
            cin >> x;
            cnt[x] ++;
            if(cnt[x] == 1) ans ++;
            q.push(Node{t, x});
        }
        while(!q.empty() && q.front().t + 86400 <= t)
        {
            cnt[q.front().x] --;
            if(cnt[q.front().x] == 0) ans --;
            q.pop();
        }
        cout << ans << endl;
    }
    return 0;
}
posted @ 2022-11-05 18:14  yuzihang  阅读(25)  评论(0)    收藏  举报