intさわだんのBlack History

刹那的レジェンドになりたい。

第7回日本情報オリンピック 春合宿 1日目 問題3 「インフルエンザ」 (Flu)

以前バケット法でも解けますとか言ってたので解いた。


第7回日本情報オリンピック 春合宿 1日目 「インフルエンザ」 (Flu) - intさわだんのBlack History

バケット法については蟻本参照してください。

こういう問題すきです。

計算量はO(N)だと思うけれど定数係数がかなりアレなのでO(N)であってO(N)でないという哲学的なものになる。

#include <bits/stdc++.h>

using namespace std;
typedef pair<int,int> P;
int n,m,d,k,ans;
P p[100003];
bool used[1002][1002];

int nj(int x){
	return (x*x);
}
vector<P> bucket[1003][1003];

int main(){
	map<P,int> ma;
	scanf("%d%d%d%d",&n,&m,&d,&k);
	for(int i = 1;i <= n;i++){
		scanf("%d%d",&p[i].first,&p[i].second);
		ma[P(p[i].first,p[i].second)] = i;
		bucket[p[i].first/d][p[i].second/d].push_back(P(p[i].first,p[i].second));
	}
	for(int i = 0;i <= 1000;i++){
		for(int j = 0;j <= 1000;j++){
			used[i][j] = false;
		}
	}
	queue<P> que;
	que.push(P(0,1));used[p[1].first][p[1].second] = true;
	while(que.size()){
		P q = que.front(); que.pop();
		if(q.first > k)continue;
		if(q.first <= k && q.first + m > k)ans++;
		int a1 = p[q.second].first/d;
		int a2 = p[q.second].second/d;
		int jo = bucket[a1][a2].size();
		for(int i = max(0,a1-1);i <= a1 + 1;i++){
			for(int j = max(0,a2-1);j <= a2 + 1;j++){
				int bs = bucket[i][j].size();
				for(int l = 0;l < bs;l++){
					P t = bucket[i][j][l];
					if(used[t.first][t.second] == false && nj(t.first-p[q.second].first)+nj(t.second-p[q.second].second) <= d*d){
						used[t.first][t.second] = true;
						que.push(P(q.first+1,ma[P(t.first,t.second)]));
					}
				}
			}
		}
	}
	printf("%d\n",ans);

	return 0;
}