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;
}
拙いものと思えども、
その手に握る其れこそが、
いつか幻想を生んでいく。