【题意总结】

他按照时间记录下了到达海港的每一艘船只情况;对于第 ii 艘到达的船,他记录了这艘船到达的时间 tit_i (单位:秒),船上的乘客数 kik_i,以及每名乘客的国籍 xi,1,xi,2...xi,kx_{i,1},x_{i,2}...x_{i,k}

题目共输入 nn 艘船的数据,每份数据中包含第 ii 艘船的到达时间 tit_i、这艘船上搭载的乘客数量 kik_i 以及船上每名乘客的国籍 xi,jx_{i,j}

要求输出的是在每一艘船到达港口时,计算前 24 个小时(86400秒)中(包含这一秒),所有到达港口的船上所有的乘客是来自多少个国家的。

抽象一点地说,这题会输入 nn 条信息组,其中的第 ii 组信息中会包含它的时间编号 tit_i、元素数量 kik_i 以及每个元素的类别。要求输出 nn 行,每行输出以 tit_i 为起点向前 86400 秒内所有元素共有多少个类别。

简单地想想即可看出队列的结构: 前面输入的某个元素如果与当前输入的元素之间的时间差超过 86400 秒,那么这个元素就永远不会参与计算了,也就可以说被弹出了。

先输入的元素会被先弹出,明显的队列结构。

进一步能够想到滑动窗口,这题能够被看成一个以秒为单位的长度为 86400 的滑动窗口,只是要输出以每个输入的时间 tit_i 为右端点的窗口中元素的类别之和即可。

【样例计算】

#1:

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

3
4
4


一共有 33 艘船。 第一艘:于第 11 秒到达海港,船上共有 44 名乘客。最近 2424 小时内到达的船有:第一艘,这些船上共有 44 名乘客,来自国家:4,1,2,24,1,2,2,共有 33 个不同的国家。

第二艘:于第 22 秒到达海港,船上共有 22 名乘客。最近 2424 小时内到达的船有:第一艘、第二艘,这些船上共有 4+2=64+2=6 名乘客,来自国家:4,1,2,2,2,34,1,2,2,2,3,共有 44 个不同的国家。

第三艘:于第 1010 秒到达海港,船上共有 11 名乘客。最近 2424 小时内到达的船有:第一艘、第二艘、第三艘,这些船上共有 4+2+1=74+2+1=7 名乘客,来自国家:4,1,2,2,2,3,34,1,2,2,2,3,3,共有 44 个不同的国家。

#2

4
1 4 1 2 2 3
3 2 2 3
86401 2 3 4
86402 1 5
3
3
3
4

一共有 44 艘船。 第一艘:于第 11 秒到达海港,船上共有 44 名乘客。最近 2424 小时内到达的船有:第一艘,这些船上共有 44 名乘客,来自国家:1,2,2,31,2,2,3,共有 33 个不同的国家。

第二艘:于第 33 秒到达海港,船上共有 22 名乘客。最近 2424 小时内到达的船有:第一艘、第二艘,这些船上共有 4+2=64+2=6 名乘客,来自国家:1,2,2,3,2,31,2,2,3,2,3,共有 33 个不同的国家。

第三艘:于第 8640186401 秒到达海港,船上共有 22 名乘客。最近 2424 小时内到达的船有:第二艘、第三艘,这些船上共有 2+2=42+2=4 名乘客,来自国家:2,3,3,42,3,3,4,共有 33 个不同的国家。

第四艘:于第 8640286402 秒到达海港,船上共有 11 名乘客。最近 2424 小时内到达的船有:第二艘、第三艘、第四艘,这些船上共有 2+2+1=52+2+1=5 名乘客,来自国家:2,3,3,4,52,3,3,4,5,共有 44 个不同的国家。

思路

以每个人为单位,需要记录每个人的到达时间和国籍,所以先创建一个结构体 P ,再创建一个 P 类型的队列 peo ,用它来模拟滑动窗口的过程,再使用一个桶数组来记录每个国家有没有人。

但是这个方法会有两层循环,在最坏情况下会有 3×105×105=3×10103\times 10^5\times 10^5=3\times 10^{10} 的时间复杂度,明显的 Time Exceeded

那么可不可以在一层循环的基础上动态更新计数变量 sum 呢?

更新条件: 当桶数组中的某一项 cnticnt_i 的值从 00 变成 11 时,代表又出现了一个新的国籍,sum++。 当桶数组中的某一项 cnticnt_i 的值从 11 变成 00 时,代表这 2424 个小时内出现的国籍数量又减少了一个,sum--

示例代码

#include <bits/stdc++.h>
using namespace std;

struct P{
	int time,ne;
};
const int N=1e5+5;
int n,k,t,x,sum,cnt[N];
queue<P> peo;

int main(){
	freopen("port.in","r",stdin);
	freopen("port.out","w",stdout);
	ios::sync_with_stdio(false);
	cin.tie(0);                        
	cout.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++){
	    cin>>t>>k;
	    for(int j=1;j<=k;j++){
	    	cin>>x;
	    	peo.push({t,x});
	    	cnt[x]++;
	    	if(cnt[x]==1) sum++;
		}
		while(t-86400>=peo.front().time){
			cnt[peo.front().ne]--;
			if(cnt[peo.front().ne]==0) sum--;
			peo.pop();
		}
		cout<<sum<<'\n';
	}
	return 0;
}