题目:Giant For
题意:
一个容器有三种操作:
add x y: 增加一坐标。
remove x y: 去除一坐标。
find x y: 查找容器里的一坐标使得其座标值大于x y,如果有多组值,按主以x次以y排序,输出最小x, y
(0 <= x, y<= 1000000000)
解题思路:
用线段树维护坐标点,以x值作为叶结点,然后第个结点保存其子树的最大y值,如果find x, y,从根结点开始,往符合条件的子树深入,即往子树有大于x的叶结点和大于y值的结点的子树前进
这里x,y值很大,数组开不下去,但操作数最多才200000,也就是最多才有200000对不同的数,首选输入所有的操作,按x从小到大排序数值,可以以坐标号代替x,这就是离散化了,很多时候都很有用。处理的时候要注意相同值的影响。
![ContractedBlock.gif](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <iostream>
2 #include <cstdio>
3 #include <string>
4 #include <cstring>
5 #include <algorithm>
6 #include <vector>
7 #include <map>
8
9 using namespace std;
10
11 const int MAX = 200000 + 10;
12 struct TTree
13 {
14 int left, right, maxCol;
15 }Tree[4 * MAX];
16
17 struct TCoord
18 {
19 bool operator == (const TCoord& b)
20 {
21 return row == b.row && col == b.col;
22 }
23 int row, col;
24 }Coord[MAX];
25
26 int Hash[MAX];
27 int Pos[MAX];
28 char OP[MAX][10];
29
30 bool comp(int i, int j)
31 {
32 if(Coord[i].row != Coord[j].row)
33 return Coord[i].row < Coord[j].row;
34 else
35 return Coord[i].col < Coord[j].col;
36 }
37
38 int myMax(int a, int b)
39 {
40 return a < b ? b : a;
41 }
42
43 void build(int left, int right, int num)
44 {
45 Tree[num].maxCol = 0;
46 Tree[num].left = left;
47 Tree[num].right = right;
48 if(left == right)
49 return;
50 int mid = (left + right) >> 1;
51 build(left, mid, 2 * num);
52 build(mid + 1, right, 2 * num + 1);
53 }
54
55 void insert(int row, int col, int num)
56 {
57 if(Tree[num].left == Tree[num].right)
58 {
59 Tree[num].maxCol = col;
60 return;
61 }
62 int mid = (Tree[num].left + Tree[num].right) >> 1;
63 if(row <= mid)
64 insert(row, col, 2 * num);
65 else
66 insert(row, col, 2 * num + 1);
67 Tree[num].maxCol = myMax(Tree[2 * num].maxCol, Tree[2 * num + 1].maxCol);
68 }
69
70 void remove(int row, int col, int num)
71 {
72 if(Tree[num].left == Tree[num].right)
73 {
74 Tree[num].maxCol = 0;
75 return;
76 }
77 int mid = (Tree[num].left + Tree[num].right) >> 1;
78 if(row <= mid)
79 remove(row, col, 2 * num);
80 else
81 remove(row, col, 2 * num + 1);
82 Tree[num].maxCol = myMax(Tree[2 * num].maxCol, Tree[2 * num + 1].maxCol);
83 }
84
85 int find(int row, int col, int num)
86 {
87 if(Tree[num].maxCol <= col)
88 return -1;
89 if(Tree[num].left == Tree[num].right)
90 {
91 if (Coord[Pos[Tree[num].left]].row > Coord[Pos[row]].row)
92 return num;
93 else
94 return -1;
95 }
96
97 int mid = (Tree[num].left + Tree[num].right) >> 1;
98 int res;
99 if(mid > row)
100 {
101 res = find(row, col, 2 * num);
102 if(res != -1)
103 return res;
104 }
105 if(Tree[num].right > row)
106 {
107 res = find(row, col, 2 * num + 1);
108 if(res != -1)
109 return res;
110 }
111 return -1;
112 }
113
114 int main()
115 {
116 freopen("in.txt","r",stdin);
117 int N;
118 int T = 1;
119 while(scanf("%d", &N) == 1 && N)
120 {
121 if(T != 1)
122 printf("\n");
123 printf("Case %d:\n", T++);
124 for(int i = 0; i < N; ++i)
125 {
126 scanf("%s%d%d", OP[i], &Coord[i].row, &Coord[i].col);
127 Pos[i] = i;
128 }
129 sort(Pos, Pos + N, comp);
130 Hash[Pos[0]] = 0;
131 int flag = 0;
132 for(int i = 1; i < N; ++i)
133 {
134 if(Coord[Pos[i]] == Coord[Pos[i - 1]])
135 Hash[Pos[i]] = flag;
136 else
137 {
138 Hash[Pos[i]] = ++flag;
139 Pos[flag] = Pos[i];
140 }
141 }
142 build(0, flag, 1);
143 for(int i = 0; i < N; ++i)
144 {
145 if(strcmp(OP[i], "add") == 0)
146 insert(Hash[i], Coord[i].col, 1);
147 else if(strcmp(OP[i], "remove") == 0)
148 remove(Hash[i], Coord[i].col, 1);
149 else
150 {
151 int ans = find(Hash[i], Coord[i].col, 1);
152 if(ans != -1)
153 printf("%d %d\n", Coord[Pos[Tree[ans].left]].row, Tree[ans].maxCol);
154 else
155 printf("-1\n");
156 }
157 }
158 }
159 return 0;
160 }