P2058 海港
首先上来要分析复杂度。
这道题的的数据规模如下
如果用纯暴力的话:
首先是空间绝对爆炸,但先不管这个
来计算一下时间复杂度:
n是小于等于,其中ki的数据规模给的很隐晦,因为是,所以ki最多只能项
然后暴力的话时间复杂度就是,大概就是
看来不仅爆空间,时间也爆
升级一小点:
用队列维护(一定得用STL的了,因为空间太大,需要动态内存)
queue里存结构体,结构体里存时间加人数加记录的国籍数组
时间超了就扔,最大储存不过86400项
额,负优化了
再看看为什么ki给的那么隐晦,绝对有出题人的小心思
还是用队列维护(当然还是用STL)
不过往队列里存人,不存船
每个人用结构体存,里面存一个国籍加时间
往队列加的时候做去重操作
估一下,因为,所以在每一项都不同的情况下最多800项(1加到800等于320400)
时间超了的人照样扔
然后每次都遍历一下队列,数数在队列还有多少个国籍
算一算时间复杂度,大概是
k不超800,最多循环
可以啊,正巧压 ,perfect!
但是正好压,也不好,万一常数大一点给卡常了怎么办 毕竟众所周知CCF的老爷机子有多慢
于是乎,我们再优化
用数组来储存目前这个国籍的有多少人,属于哈希思想
用一个变量来储存每次有多少国籍
队列每增加一个人便在对应的国籍上++,并且如果加完后只有他1人,说明新添了个国籍,便在国籍数上++
在队列里筛人的时候如果目前筛掉了并且剩下只有0人的话,说明有一个国籍没人了,便在国籍数上--
每次输出国籍数即可
这下再算算时间复杂度,只有
perfect!
剩下的,只有代码了:
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
struct people{
int t,k;
};
queue<people>q;
int a[3*100000];
int main(){
int n,ans=0;
scanf("%d",&n);
for (int i=0;i<n;i++){
int x,y;
scanf("%d%d",&x,&y);
while ((!q.empty()) && x-q.front().t>=86400){
a[q.front().k]--;
if (!a[q.front().k]) ans--;
q.pop();
}
people p;
p.t=x;
for (int j=0,k;j<y;j++){
scanf("%d",&k);
p.k=k;
q.push(p);
a[k]++;
if (a[k]==1) ans++;
}
printf("%d\n",ans);
}
return 0;
}