LUOGU P2058 海港

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

題目分析
經過的仔細閱讀,我們可以將題意理解爲:給出多組船的信息,求在一天的範圍內的不同船的種類
我們可以很自然的想到隊列的維護

這裏,我們按船的信息來作爲隊列的元素的
對於前一天的無用信息,我們進行出隊處理

在維護上面是比較容易寫的,對於每一個進來的信息,給其相應的種類的計數的桶累加
當然,第一個元素的入隊我們要特判一下,然後後面是出隊,
最後是判斷當前元素是不是第一次被加進來,累加一下當前不同的種類的個數就行了

但是,我在寫的時候有一個地方出了一些問題,
對於這道題目,有可能出現的問題便是重複和邊界了,
由於邊界不是很大,所以並不需要過分考慮,所以我們來把焦點匯聚到重複上面
經過思考,我發現類似以下的數據,可以卡掉:
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++

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章