1. 程式人生 > >codeforces Gym

codeforces Gym

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