题目概况
链接: https://www.luogu.com.cn/problem/P2058
难度: 普及/提高-
题目分析
一般简单的滑动窗口模板题.
因为时间是按照从小到大的顺序给出的,所以时间上就满足了单调递增性;而题目要求的是“每一艘到达时间为止的24小时”,本质上就是一个窗口.
根据上述性质,我们可以统计每种国籍的人数,对于从未出现的国籍将ans
加1,但如果队列中的队头的时间已经超过了限定,我们就要“滑出”窗口,那么相应地,滑出的人的对应国籍数减1,如果该国籍的人已经没有了,ans减1.
我们还需要用到一种叫双端队列的数据结构.双端队列可以对队列和队尾进行自由操作,以满足不同题目中滑动窗口的动态性.
代码
#include <iostream>
#include <deque>
using namespace std;
const int N = 1e5 + 5;
struct Node {
int t; //到达时间
int x; //此人国籍
Node (int _t, int _x) {
t = _t, x = _x;
}
};
int n, ans;
int v[N];
deque <Node> q; //双端队列
int main() {
scanf("%d", &n);
while (n--) {
int t, k, x;
scanf("%d%d", &t, &k);
for (int i = 1; i <= k; i++) {
scanf("%d", &x);
if (!v[x]) {
ans++;
}
v[x]++;
q.push_back(Node(t, x)); //进入队列
}
while (t - q.front().t >= 86400) {
v[q.front().x]--; //该人所属国籍总人数相应减1
if (!v[q.front().x]) ans--; //没人了答案相应减1
q.pop_front(); //滑出去
}
printf("%d\n", ans);
}
return 0;
}