bzoj3276 磁力

算法竞赛进阶指南p219,这里是分块。
当然也可以树套树来个动态二维数点。

#include <algorithm>
#include <iostream>
#include <cstdio>
#include <queue>
#include <cmath>
using namespace std;
typedef long long ll;
int xx, yy, n, uu, vv, blc, beg[505], zdz[505], ans;
double dis[250005];
bool vis[250005];
queue<int> d;
struct Node{
	int mm, pp, rr, be;
	double di;
}nd[250005];
bool cmp1(Node x, Node y){
	return x.mm<y.mm;
}
bool cmp2(Node x, Node y){
	if(x.be==y.be)	return x.di<y.di;
	else	return x.be<y.be;
}
int main(){
	cin>>xx>>yy>>nd[0].pp>>nd[0].rr>>n;
	blc = sqrt(n);
	for(int i=1; i<=n; i++){
		scanf("%d %d %d %d %d", &uu, &vv, &nd[i].mm, &nd[i].pp, &nd[i].rr);
		nd[i].di = sqrt(ll(uu-xx)*ll(uu-xx)+ll(vv-yy)*ll(vv-yy));
	}
	sort(nd+1, nd+1+n, cmp1);
	for(int i=1; i<=n; i++)
		nd[i].be = (i - 1) / blc + 1;
	for(int i=1; i<=nd[n].be; i++){
		beg[i] = (i - 1) * blc + 1;
		zdz[i] = nd[min(n,i*blc)].mm;
	}
	sort(nd+1, nd+1+n, cmp2);
	d.push(0);
	while(!d.empty()){
		int x=d.front();
		ans++;
		d.pop();
		int k=upper_bound(zdz+1, zdz+1+nd[n].be, nd[x].pp)-zdz;
		for(int i=1; i<=k-1; i++){
			int &j=beg[i];
			while(nd[j].di<=nd[x].rr && j<=min(i*blc,n)){
				if(!vis[j])	d.push(j);
				vis[j++] = true;
			}
		}
		int i=beg[k];
		if(!i)	continue;
		while(nd[i].di<=nd[x].rr && i<=min(k*blc, n)){
			if(nd[i].mm<=nd[x].pp && !vis[i]){
				vis[i] = true;
				d.push(i);
			}
			i++;
		}
	}
	cout<<ans-1<<endl;
	return 0;
}
原文地址:https://www.cnblogs.com/poorpool/p/8485777.html