题目描述
小 K 是一个海港的海关工作人员,每天都有许多船只到达海港,船上通常有很多来自不同国家的乘客。
小 K 对这些到达海港的船只非常感兴趣,他按照时间记录下了到达海港的每一艘船只情况;对于第 ii 艘到达的船,他记录了这艘船到达的时间 t_iti (单位:秒),船上的乘客数 k_iki,以及每名乘客的国籍 x_{i,1}, x_{i,2},\dots,x_{i,k}xi,1,xi,2,…,xi,k。
小K统计了 n 艘船的信息,希望你帮忙计算出以每一艘船到达时间为止的 24 小时(24 小时 =86400=86400 秒)内所有乘船到达的乘客来自多少个不同的国家。
形式化地讲,你需要计算 nn 条信息。对于输出的第 ii 条信息,你需要统计满足 t_i-86400<t_p \le t_iti−86400<tp≤ti 的船只 pp,在所有的 x_{p,j}xp,j
中,总共有多少个不同的数
输入格式
第一行输入一个正整数 nn,表示小 K 统计了 nn 艘船的信息。
接下来 nn 行,每行描述一艘船的信息:前两个整数 t_iti 和 k_iki 分别表示这艘船到达海港的时间和船上的乘客数量,接下来 k_iki 个整数 x_{i,j}xi,j 表示船上乘客的国籍。
保证输入的 t_iti 是递增的,单位是秒;表示从小K第一次上班开始计时,这艘船在第 t_iti 秒到达海港。
保证 1 \le n \le 10^51≤n≤105,\sum{k_i} \le 3\times 10^5∑ki≤3×105 ,1\le x_{i,j} \le 10^51≤xi,j≤105, 1 \le t_{i-1}\le t_i \le 10^91≤ti−1≤ti≤109。
其中 \sum{k_i}∑ki 表示所有的 k_iki 的和。
输出格式
输出n行,第i行输出一个整数表示第i艘船到达后的统计信息。
样例输入
3 1 4 4 1 2 2 2 2 2 3 10 1 3
样例输出
3 4 4
样例输入
4 1 4 1 2 2 3 3 2 2 3 86401 2 3 4 86402 1 5
样例输出
3 3 3 4
问题提示
【样例1说明】
第一艘船在第1秒到达海港,最近24小时到达的船是第一艘船,共有4个乘客,分别是来自国家4、1、2、2,共来自3个不同的国家;
第二艘船在第2秒到达海港,最近24小时到达的船是第一艘船和第二艘船,共有4+2=6个乘客,分别是来自国家4、1、2、2、2、3,共来自4个不同的国家;
第三艘船在第10秒到达海港,最近24小时到达的船是第一艘船、第二艘船和第三艘船,共有4+2+1=7个乘客,分别是来自国家4、1、2、2、2、3、3,共来自4个不同的国家。
【样例2说明】
第一艘船在第1秒到达海港,最近24小时到达的船是第一艘船,共有4个乘客,分别是来自国家1、2、2、3,共来自3个不同的国家;
第二艘船在第3秒到达海港,最近24小时到达的船是第一艘船和第二艘船,共有4+2=6个乘客,分别是来自国家1、2、2、3、2、3,共来自3个不同的国家;
第三艘船是在第86401秒到达海港,最近24小时到达的船是第二艘船和第三艘船,共有2+2=4个乘客,分别是来自国家2、3、3、4,共来自3个不同的国家;
第四艘船在第86402秒到达海港,最近24小时到达的船是第二艘船、第三艘船和第四艘船,共有2+2+1=5个乘客,分别是来自国家2、3、3、4、5,共来自4个不同的国家。
思路
运用尺取法,求解24小时内所有不同的国籍,详细解释见代码
程序实现
#include <iostream>
#include <queue>
#include <cstdio>
using namespace std;
#define int long long
#define F(i,a,b) for(int i=(a);i<=(b);i++)
#define R(i,a,b) for(int i=(a);i>=(b);i--)
const int N=1e5+5;
int n,k,t,x,ans;
int cnt[N];
//定义结构体,存储时间与国籍
struct Node
{
int t,x;
};
//队列记录符合条件的时间与国籍
queue<Node> q;
signed main()
{
//读入数据
scanf("%lld",&n);
//从一到n遍历第i艘船到达时间为止的24小时内所有乘船到达的乘客来自多少个不同的国家
F(i,1,n)
{
//读入数据
scanf("%lld%lld",&t,&k);
F(j,1,k)
{
cin>>x;
//哈希记录此国籍
cnt[x]++;
//如果是新国籍,ans加一
if(cnt[x]==1) ans++;
//将国际与时间读入队列
q.push(Node{t,x});
}
//如果队不空且第一个时间与最后一个时间差>=24时时,将此时间与国籍弹出队列
while(!q.empty() && q.front().t+86400<=t)
{
//将此国籍的数量减一
cnt[q.front().x]--;
//如果此国籍没有了,ans减一
if(cnt[q.front().x]==0) ans--;
//将此时间与国籍弹出队列
q.pop();
}
//输出答案
cout<<ans<<"\n";
}
return 0;
}