题意:给了三种操作
1:add(x,y)将这个点加入二维坐标系
2:remove(x,y)将这个点从二维坐标系移除。
3:find(x,y)就是找到在(x,y)右上方的第一个点。
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.NavigableSet;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeSet;
public class Main {
public static void main(String[] args) {
new CF_19D().run();
}
}
class CF_19D {
void run() {
InputReader cin = new InputReader(System.in);
PrintWriter cout = new PrintWriter(new BufferedOutputStream(System.out));
int n = cin.nextInt();
for (int i = 0; i < n; i++) {
switch (cin.next()) {
case "add":
operator[i] = 0;
break;
case "remove":
operator[i] = 1;
break;
case "find":
operator[i] = 2;
break;
}
x[i] = cin.nextInt();
y[i] = cin.nextInt();
}
Hash h = new Hash(n, x);
int limit = h.length() - 1;
for (int i = 0; i <= limit; i++)
set[i].clear();
buildTree(1, 0, limit);
for (int i = 0; i < n; i++) {
int id = h.idx(x[i]);
if (operator[i] == 0) {
set[id].add(y[i]);
update(id, set[id].isEmpty() ? 0 : set[id].last(), 1, 0, limit);
} else if (operator[i] == 1) {
set[id].remove(y[i]);
update(id, set[id].isEmpty() ? 0 : set[id].last(), 1, 0, limit);
} else {
int pos = ask(id + 1, y[i], 1, 0, limit);
if (pos == NOTFIND)
cout.println(NOTFIND);
else
cout.println(h.value(pos) + " " + set[pos].higher(y[i]));
}
}
cout.flush();
}
void buildTree(int t, int l, int r) {
left[t] = l;
right[t] = r;
max[t] = 0;
if (l == r)
return;
int mid = (l + r) >> 1;
buildTree(t << 1, l, mid);
buildTree(t << 1 | 1, mid + 1, r);
up(t);
}
void update(int i, int c, int t, int l, int r) {
if (l > r)
return;
if (l == r) {
max[t] = c;
return;
}
int mid = (l + r) >> 1;
if (i <= mid)
update(i, c, t << 1, l, mid);
else
update(i, c, t << 1 | 1, mid + 1, r);
up(t);
}
int ask(int i, int c, int t, int l, int r) {
if (max[t] <= c || i > r)
return NOTFIND;
if (l == r)
return max[t] > c ? l : NOTFIND;
int mid = (l + r) >> 1;
if (i > mid)
return ask(i, c, t << 1 | 1, mid + 1, r);
else {
int res = ask(i, c, t << 1, l, mid);
if (res != NOTFIND)
return res;
else
return ask(i, c, t << 1 | 1, mid + 1, r);
}
}
void up(int t) {
max[t] = Math.max(max[t << 1], max[t << 1 | 1]);
}
final int NOTFIND = -1;
final int N = 200_008;
int[] x = new int[N];
int[] y = new int[N];
int[] z = new int[N];
int[] operator = new int[N];
NavigableSet<Integer>[] set = new TreeSet[N];
{
for (int i = 0; i < N; i++)
set[i] = new TreeSet<Integer>();
}
int[] left = new int[N << 2];
int[] right = new int[N << 2];
int[] max = new int[N << 2];
}
class Hash {
Hash(int length, int[] array) {
Set<Integer> treeset = new TreeSet<Integer>();
for (int i = 0; i < length; i++) {
treeset.add(array[i]);
}
this.array = new int[treeset.size()];
size = 0;
for (int i : treeset)
this.array[size++] = i;
}
int length() {
return size;
}
int idx(int key) {
return Arrays.binarySearch(array, key);
}
int value(int idx) {
return array[idx];
}
int size;
int[] array;
}
class InputReader {
public BufferedReader reader;
public StringTokenizer tokenizer;
public InputReader(InputStream stream) {
reader = new BufferedReader(new InputStreamReader(stream), 32768);
tokenizer = null;
}
public String next() {
while (tokenizer == null || !tokenizer.hasMoreTokens()) {
try {
tokenizer = new StringTokenizer(reader.readLine());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return tokenizer.nextToken();
}
public int nextInt() {
return Integer.parseInt(next());
}
public long nextLong() {
return Long.parseLong(next());
}
}