http://acm.hdu.edu.cn/showproblem.php?pid=4400
Problem Description
Terrorists put some mines in a crowded square recently. The police evacuate all people in time before any mine explodes. Now the police want all the mines be ignited. The police will take many operations to do the job. In each operation, the police will ignite
one mine. Every mine has its "power distance". When a mine explodes, any other mine within the power distance of the exploding mine will also explode. Please NOTE that the distance is Manhattan distance here.
More specifically, we put the mines in the Cartesian coordinate system. Each mine has position (x,y) and power distance d.
The police want you to write a program and calculate the result of each operation.
Input
There are several test cases.
In each test case:
Line 1: an integer N, indicating that there are N mines. All mines are numbered from 1 to N.
Line 2…N+1: There are 3 integers in Line i+1 (i starts from 1). They are the i-th mine’s position (xi,yi) and its power distance di. There can be more than one mine in the same point.
Line N+2: an integer M, representing the number of operations.
Line N+3...N+M+2 : Each line represents an operation by an integer k meaning that in this operation, the k-th mine will be ignited. It is possible to ignite a mine which has already exploded, but it will have no effect.
1<=M<=N<=100000,0<=xi,yi<=10^9,0<=di<=10^9
Input ends with N=0.
Output
For each test case, you should print ‘Case #X:’ at first, which X is the case number starting from 1. Then you print M lines, each line has an integer representing the number of mines explode in the correspondent operation.
Sample Input
3 0 0 0 1 1 2 2 2 2 3 1 2 3 0
Sample Output
Case #1: 1 2 0
/*** hdu4400 STL应用 题目大意:在二维坐标系中给出一些点,每次爆炸一些点,每个点都有一个爆炸半径,在半径内的点会接着爆炸,已经爆炸过的不再爆炸,问每次给定一个爆炸点 能有多少炸弹在此次爆炸。注意:点和点之间的距离为曼哈顿距离,而且有重合的点 解题思路:离散化横坐标,对对于每一个横坐标建立一个vector容器,然后将每个容器里的点从小到大排列,然后从小到大排序横坐标,利用lower_bound查找即可。 */ #include <stdio.h> #include <string.h> #include <algorithm> #include <iostream> #include <vector> #include <queue> using namespace std; const int maxn = 110005; const int inf = 2000000005; struct node { int y,dis; node(){} node(int y,int dis) { this->y=y; this->dis=dis; } bool operator <(const node &other)const { if(y==other.y)return dis<other.dis; return y<other.y; } }; vector<node>vec[maxn]; struct point { int x,y,dis; point(){} point(int x,int y,int dis) { this->x=x; this->y=y; this->dis=dis; } }po[maxn]; queue<point>q; int n,m,Hash[maxn]; int main() { int tt=0; while(~scanf("%d",&n)) { if(n==0)break; for(int i=0;i<maxn;i++)///各个容器清空 { vec[i].clear(); } int num=0; for(int i=1;i<=n;i++) { scanf("%d%d%d",&po[i].x,&po[i].y,&po[i].dis); Hash[num++]=po[i].x;///储存所有点的横坐标 } sort(Hash,Hash+num); num=unique(Hash,Hash+num)-Hash;///去重,num为去重后的个数 for(int i=1;i<=n;i++)///对于每个横坐标x视为一个容器 { int id=lower_bound(Hash,Hash+num,po[i].x)-Hash; vec[id].push_back(node(po[i].y,po[i].dis)); } for(int i=0;i<num;i++)///每个横坐标容器排序 { sort(vec[i].begin(),vec[i].end()); } scanf("%d",&m); printf("Case #%d:\n",++tt); for(int i=1;i<=m;i++) { int k,ret=0;; scanf("%d",&k); while(!q.empty())q.pop(); vector<node>::iterator it1,it2,it; q.push(point(po[k].x,po[k].y,po[k].dis)); while(!q.empty()) { point now=q.front(); q.pop(); ///确定可及横坐标范围 int x=lower_bound(Hash,Hash+num,now.x-now.dis)-Hash; int y=upper_bound(Hash,Hash+num,now.x+now.dis)-Hash; for(;x<y;x++) { int t=Hash[x];///t为正在查找的横坐标点 int yy=now.dis-abs(t-now.x);///该横坐标下的纵坐标可及最大值 int id=lower_bound(Hash,Hash+num,t)-Hash; it1=lower_bound(vec[id].begin(),vec[id].end(),node(now.y-yy,-1)); it2=lower_bound(vec[id].begin(),vec[id].end(),node(now.y+yy,inf)); it=it1; for(;it1<it2;it1++) { node tmp=*it1; q.push(point(t,tmp.y,tmp.dis)); ret++; } vec[id].erase(it,it2);///删除已经经历过的点 } } printf("%d\n",ret); } } return 0; }