LUOGU P2058 海港

mac2022-06-30  14

题目分析 经过的仔细阅读,我们可以将题意理解为:给出多组船的信息,求在一天的范围内的不同船的种类 我们可以很自然的想到队列的维护

这里,我们按船的信息来作为队列的元素的 对于前一天的无用信息,我们进行出队处理

在维护上面是比较容易写的,对于每一个进来的信息,给其相应的种类的计数的桶累加 当然,第一个元素的入队我们要特判一下,然后后面是出队, 最后是判断当前元素是不是第一次被加进来,累加一下当前不同的种类的个数就行了

但是,我在写的时候有一个地方出了一些问题, 对于这道题目,有可能出现的问题便是重复和边界了, 由于边界不是很大,所以并不需要过分考虑,所以我们来把焦点汇聚到重复上面 经过思考,我发现类似以下的数据,可以卡掉: 2 1 3 33 33 44 86401 1 33 正确的显然是: 2 1 但是如果像上面那样写的话,答案却是: 2 2 (vis表示当前种类的种族有多少人) 这是为什么呢? 下面我们把数据带进去看一下 在第一组时,是没有任何问题的 在第二组时,我们一边入队,一边出队也是没有什么问题的,真正卡掉的是判断的条件 在第二组时,我们首先将元素入队,可以发现vis[33]=3,之后把前面的扔出去,vis[33]=1——又符合了一种新物种的判断条件!GG 所以我们需要的调整是,把出队和入队分开, 入队还是做入队的事情,出队还是考虑出队的事情,只是在入队时考虑好新的种类,再在出队时考虑上一船的人下完了,相应种族的灭绝再在上面累加的上面减,如果当前的种类上一次也有就不用加,当然出队时也只会留下一个

代码

#include <bits/stdc++.h> using namespace std; struct node { int k; //种类 long long t; //上船时间 }p[1000009]; int m,n; long long T; int h = 1, w = 1; long long s; int vis[1000009]; //当前种类个数 int a[1000009]; bool jud = true; //用于第一个的特判 int main() { scanf("%d",&m); while (m--) { scanf("%lld %d",&T,&n); for (int i = 1; i <= n; i++) scanf("%d",&a[i]); for (int i = 1; i <= n; i++) { if (jud) p[h].k = a[i], p[h].t = T, vis[a[i]]++, jud = false; //第一个元素特判 else w++, p[w].k = a[i], p[w].t = T, vis[a[i]]++; //常规操作 if (vis[a[i]] == 1) s++; //看看是不是新的种类 } while (p[w].t - p[h].t >= 86400) { //出队 vis[p[h].k]--; //当前种族个数递减 if (vis[p[h].k] == 0) s--; //种族灭绝 h++; //队头后移 } printf("%lld\n",s); } return 0; }

crx CSP-J/S RP++

最新回复(0)