hdu4400 STL應用 查詢思維題

life4711發表於2015-03-29

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;
}


相關文章