Problem A. Archery Tournament
Time limit: 3 seconds
You were invited to the annual archery tournament. You are going to compete against the best archers from all of the Northern Eurasia. This year, a new type of competition is introduced, where a shooting range is dynamic and new targets might appear at any second. As the shooting range is far enough from you, it can be represented as a 2D plane, where y = 0 is the ground level. There are some targets in a shape of a circle, and all the targets are standing on the ground. That means, if a target’s center is (x, y) (y > 0), then its radius is equal to y, so that it touches the line y = 0. No two targets simultaneously present at the range at any given time intersect (but they may touch). Initially, the shooting range is empty. Your participation in this competition can be described as n events: either a new target appears at the range, or you shoot an arrow at some point at the range. To hit a target, you must shoot strictly inside the circle (hitting the border does not count). If you shoot and hit some target, then the target is removed from the range and you are awarded one point.
Input
The first line of the input contains integer n (1 ≤ n ≤ 2·105 ). Next n lines describe the events happening at the tournament. The i-th line contains three integers ti , xi , and yi (ti = 1, 2; −109 ≤ xi , yi ≤ 109 ; yi > 0). • If ti = 1, then a new target with center (xi , yi) and radius yi appears at the range. • If ti = 2, then you perform a shot, which hits the range at (xi , yi).
Output
For each of your shots, output a separate line with the single integer. If the shot did not hit any target, print “-1”. If the shot hit a target, print the number of event when that target was added to the range. Events are numbered starting from 1.
Examples
input
8
1 0 12
2 - 11 22
1 24 10
1 12 3
2 12 12
2 16 14
1 28 15
2 3 6
output
-1
-1
3
1
Note
Illustration shows the state of the range after first six events. The rightmost target was hit by the last shot and is going to be removed.
一、原题地址
二、大致题意
给出n个操作,
操作1表示建立一个位于(x,y)且半径为y的靶子。
操作2表示往(x,y)处开一枪。
要求在每次开枪的时候,给出枪是否命中了靶子,若命中了则输出靶子的编号,并且删除这个靶子,若没有命中则输出-1
三、思路
将靶子的横轴坐标离散在线段树上。
在线段树上的每个节点开一个set,用以记录在这个区间内存在的靶子编号。
对于每次开枪的操作,查询并且删除。
四、代码
#include <vector>
#include <iostream>
#include <string>
#include <map>
#include <stack>
#include <cstring>
#include <queue>
#include <list>
#include <cstdio>
#include <set>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <iomanip>
#include <cctype>
#include <sstream>
#include <iterator>
#include <functional>
#include <stdlib.h>
#include <time.h>
#include <bitset>
using namespace std;
#define LL long long
const int inf = 0x3f3f3f3f;
const double eps = 1e-6;
int n;
LL a[400005];
int tot;
struct Node
{
int t;
LL l, r;
}op[200005];
void read()
{
scanf("%d", &n);
tot = 0;
for (int i = 1; i <= n; i++)
{
scanf("%d %lld %lld", &op[i].t,
&op[i].l, &op[i].r);
if (op[i].t == 1)
{
a[tot++] = op[i].l - op[i].r;
a[tot++] = op[i].l + op[i].r;
}
else
a[tot++] = op[i].l;
}
}
const int N = 400005;
struct Tree
{
int l, r;
set<int>id;
int mid()
{
return (l + r) >> 1;
}
}tree[N << 2]; //tree[].l, tree[].r分别表示某个节点的左右区间,这里的区间是闭区间
void build(int l, int r, int rt)
{
tree[rt].l = l;
tree[rt].r = r;
if (l == r)
{
return;
}
int m = tree[rt].mid();
build(l, m, (rt << 1));
build(m + 1, r, (rt << 1 | 1));
}
void update(int c, int ql, int qr, int l, int r, int rt)
{
if (l == ql&&r == qr)
{
tree[rt].id.insert(c);
return;
}
int m = tree[rt].mid();
if (qr <= m)update(c, ql, qr, l, m, rt << 1);
else if (ql > m)update(c, ql, qr, m + 1, r, rt << 1 | 1);
else
{
update(c, ql, m, l, m, rt << 1);
update(c, m + 1, qr, m + 1, r, rt << 1 | 1);
}
}
int Query(int l,int r,int rt,int pos,int c)
{
set<int>::iterator it = tree[rt].id.begin(), end = tree[rt].id.end();
for (; it != end; it++)
{
LL x = op[*it].l, y = op[*it].r;
if ((long long)(op[c].l - x)*(op[c].l - x) + (long long)(op[c].r - y)*(op[c].r - y) < (LL)y*y)
{
return *it;
}
}
if (l == r)
return -1;
int m = tree[rt].mid();
if (pos <= m)return Query(l, m, rt << 1, pos, c);
else return Query(m + 1, r, rt << 1 | 1, pos, c);
}
void Er(int l, int r, int rt, int ql, int qr, int c)
{
if (l == ql&&r == qr)
{
tree[rt].id.erase(c);
return;
}
int m = tree[rt].mid();
if (qr <= m)
Er(l, m, rt << 1, ql, qr, c);
else if (ql > m)
Er(m + 1, r, rt << 1 | 1, ql, qr, c);
else
{
Er(l, m, rt << 1, ql, m, c);
Er(m + 1, r, rt << 1 | 1, m+1, qr, c);
}
}
void solve()
{
sort(a + 1, a + tot + 1);
tot = unique(a + 1, a + 1 + tot) - (a + 1);
build(1, tot, 1);
for (int i = 1; i <= n; i++)
{
if (op[i].t == 1)
{
int posl = lower_bound(a + 1, a + 1 + tot, op[i].l - op[i].r) - a ;
int posr = lower_bound(a + 1, a + 1 + tot, op[i].l + op[i].r) - a ;
update(i, posl, posr, 1, tot, 1);
}
else
{
int pos = lower_bound(a + 1, a + 1 + tot, op[i].l) - a ;
int tt = Query(1, tot, 1, pos, i);
if (tt == -1)
printf("-1\n");
else
{
printf("%d\n", tt);
int posl = lower_bound(a + 1, a + 1 + tot, op[tt].l - op[tt].r) - a;
int posr = lower_bound(a + 1, a + 1 + tot, op[tt].l + op[tt].r) - a;
Er(1, tot, 1, posl, posr, tt);
}
}
}
}
int main()
{
read();
solve();
getchar();
getchar();
}