Gym - 101630A - Archery Tournament (线段树)

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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值