hdu4400 STL应用 查找思维题

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;
}
时间: 2024-08-25 23:16:30

hdu4400 STL应用 查找思维题的相关文章

Unique Encryption Keys (思维题 预处理)

题目 题意:给m个数字, q次询问, 询问b到e之间如果有重复数字就输出, 没有就输出OK 思路:用f[i]数组 记录从i开始向后最近的有重复数字的 位置, 如 1 3 2 2, 则f[1] = 4; 如果离a最近的重复数字的位置 都大于b, 就说明没有重复数字. f[]数组需要预处理,从后向前. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <vector>

sdut 2847 Monitor (思维题)

题目 题意:给定a, b, x, y;  求使c, d; 使c:d = x :y; 且c<=a, d<=b, 而且c, d尽量大. 先求最小倍数, 再用最小倍数乘 x, y; 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 using namespace std; 6 7 long long gcd(long long a, l

hdu 4972 A simple dynamic programming problem (转化 乱搞 思维题) 2014多校10

题目链接 题意:给定一个数组记录两队之间分差,只记分差,不记谁高谁低,问最终有多少种比分的可能性 分析: 类似cf的题目,比赛的时候都没想出来,简直笨到极点..... 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <cmath> 6 #include <vector> 7 #include &

学习方法_2011年编写和锻炼的思维题

1.多看,多练,多想,多总结,最重要就是不停的写代码! 给自己的目标:一天代码量最少800行,无论是什么代码,如果练习的量不够,就重复做已经写过的代码. 思维题: 找出这当中数字 1,11,31,4113,612314 的规律是怎样的? 1,11,表示前面的数有1个131,表示前面所有的数有3个14113,表示前面的所有的数有4个1.1个3以此类推,前面所有的数有6个1.2个3.1个4,即为612314 1.两个无窗的房间,其中一间有三个电灯,另一间里面有三个开关,三个开关各控制三个电灯.问:每

思维题 URAL 1718 Rejudge

题目传送门 1 /* 2 题意:数据加10组,再删掉第6组数据,问rejudge后最少最多几个作者收到邮件 3 思维题:当错在6时结果是不一定,错在7时是一定改变,因为会变成6 4 思路没错,但用结构题排序一直WA,代码有毒!学习使用set容器. 5 */ 6 #include <cstdio> 7 #include <algorithm> 8 #include <cstring> 9 #include <cmath> 10 #include <str

ZOJ 3829 贪心 思维题

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3829 现场做这道题的时候,感觉是思维题,自己智商不够,不敢搞,想着队友智商好,他们搞吧,但是没出来这题...... 以后任何时候,都自信点....该想的还是好好自己想,这类题感觉就是先去找性质,然后一点点找规律,如果必要的话,自己提出一点猜想,然后如果自己举不出来反例,就暂时认为是正确的 下午搞了一下午,发现还是悲剧,晚上参考了两个题解 http://blog.csdn.

ACM: Gym 101047K Training with Phuket&#39;s larvae - 思维题

Gym 101047K Training with Phuket's larvae Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Practice Description standard input/output Thai cuisine is known for combining seasonings so that every dish has flavors that are s

Acdreamoj1115(数学思维题)

题意:1,3是完美数,如果a,b是完美数,则2+a*b+2*a+2*b,判断给出的n是否是完美数. 解法:开始只看出来2+a*b+2*a+2*b=(a+2)*(b+2)-2,没推出更多结论,囧.没办法,只能暴力将所有的完美数求出来然后查表.正解是c+2=(a+2)*(b+2);完美数都是有质因子3或5组成的(5本身除外): 自己暴力代码: /****************************************************** * author:xiefubao *****

C++提高5 STL算法 :查找,统计,排序,拷贝,替换,算术,集合 |STL 案例:学校演讲比赛介绍

[本文谢绝转载] <大纲> STL 算法 查找算法 adjacent_find()查找容器中重复元素的首地址 distance()根据迭代器,返回元素的下标 binary_search()二分查找:在有序的序列 find   查找函数 find_if 自定义查找函数 统计算法 count 返回容器中相同元素的个数 cout_if 统计大于3的元素个数 排序算法 marge()对两个有序容器组合到另一个容器 sort 自定义排序 random_shuffle 随机洗牌 基本数据类型 random