您的位置:首页 > 其它

二维线段树之降维打击

2018-03-12 12:21 204 查看

COCI 2017/2018 ROUND#1
Deda

Little Marica is making up a nonsensical unusual fairy tale and is telling to her grandfather
who keeps interrupting her and asking her stupid intriguing questions.

In Marica’s fairy tale, N children, denoted with numbers from 1 to N by their age (from the
youngest denoted with 1, to the oldest denoted with N ), embarked on a train ride. The train
leaves from the station 0 and stops in order at stations
4000
1, 2, 3 … to infinity.

Each of the following Marica’s statements is of the form: “At stop X , child A got out” ,
where the order of these statements is completely arbitrary. In other words, it does not
depend on the station order. Her grandfather sometimes asks a question of the form:
“Based on the statements so far, of the children denoted with a number greater than
or equal to B , who is the youngest child that rode for Y or less stops?” If at the
moment the grandfather asks the question it hasn’t been said so far that a child is getting off
the train, we assume that the child is riding for an infinite amount of stops.

Marica must give a correct answer to each of her grandfather’s questions, otherwise the
grandfather will get mad and go to sleep. The answer must be correct in the moment when
the grandfather asks the question, while it can change later given Marica’s new statements,
but that doesn’t matter. Write a program that tracks Marica’s statements and answers her
grandfather’s questions.

INPUT

The first line of input contains the positive integers N and Q (2 ≤ N , Q ≤ 200 000), the

number of children and the number of statements. Each of the following Q lines describes:

● either Marica’s statement of the form “M” X A , where “M” denotes Marica, and X and

A are positive integers (1 ≤ X ≤ 1 000 000 000, 1 ≤ A ≤ N ) from the task,

● or her grandfather’s question of the form “D” Y B , where “D” denotes the grandfather,

and Y and B are positive integers (1 ≤ Y ≤ 1 000 000 000, 1 ≤ B ≤ N ) from the task.

All of Marica’s statements correspond to different children and at least one line in the input is

her grandfather’s question.

OUTPUT

For each grandfather’s question, output the number of the required child in its own line. If no

such child exists, output -1.

input input

3 4

M 10 3

M 5 1

D 20 2

D 5 1

10 10

M 20 10

D 1 9

M 2 3

D 17 10

M 20 2

D 8 2

M 40 1

D 25 2

M 33 9

D 37 9

output output

3

1

-1

-1

3

2

9

题意

一共n个人

两种操作

M X A表示 A走了X站

D Y B表示询问满足条件

{id≥Bstops≤Y{id≥Bstops≤Y

的人中id最小的是谁,不存在则-1

解法

如果用上一篇的二维线段树,在二维平面中以idid为横轴,stopstop为纵轴,每次M都新加一个值为stop的点P(id,stop)=stopP(id,stop)=stop,然后询问的则是一个矩形内所有点的最小值,用二维线段树维护矩形内最小值即可,但是二维线段树空间时间都会比一维的大,上一篇的题目时间限制为3s ,这一题为1s,所以不能用二维线段树。

这一题问的是最小值,我们知道在线段树上,左边的点坐标就是小的,点的值也可以维护最小值。

所以这一题以id为轴建立线段树,以stop为点的值,维护stop的区间最小值。
对于每次询问D Y BD Y B,则先取[B,+∞][B,+∞]上的最小值,
每次递归时检查区间的最小值是否小于等于Y,若不是,那么区间内不存在合适的点。若是,则判断当前区间是否包含于[B,+∞][B,+∞],
若是则找到id最小的(即最左边的)点来更新答案,且当左边有答案时不再向右走以减少浪费时间。

#include<iostream>
#include<stdio.h>
#include<string>
#include<string.h>
#include<algorithm>
#include<vector>
#include<set>
#include<math.h>
#include<map>
#include<stack>
using namespace std;
typedef long long LL;
const int MAX = 2e9;
int tree[2000000];
int answer;
void build(int t, int l, int r)
{
tree[t] = MAX;
if (l == r)
{
return;
}
int mid = l + r >> 1;
build(t << 1, l, mid);
build(t << 1 | 1, mid + 1, r);
}
void update(int temp, int left, int right, int B, int Y)
{
if (left == right)
{
tree[temp] = Y;
return;
}
int mid = left + right >> 1;
if (B <= mid)
update(temp << 1, left, mid, B, Y);
else
update(temp << 1 | 1, mid + 1, right, B, Y);
tree[temp] = min(tree[temp << 1], tree[temp << 1 | 1]);
}
void query(int temp, int left, int right, int Y, int B)
{
if (left == right)
{
answer = min(answer, left);
return;
}
int mid = left + right >> 1;
if (B < left)
{
if (tree[temp << 1] <= Y)
query(temp << 1, left, mid, Y, B);
else
query(temp << 1 | 1, mid + 1, right, Y, B);
}
else
{
if (B <= mid && tree[temp << 1] <= Y)
query(temp << 1, left, mid, Y, B);
if (tree[temp << 1 | 1] <= Y)
query(temp << 1 | 1, mid + 1, right, Y, B);
}
}
int main()
{
int N, Q;
scanf("%d%d", &N, &Q);
build(1, 1, N);
while (Q--)
{
char s[5];
int Y, B;
scanf("%s%d%d", s, &Y, &B);
if (s[0] == 'M')
update(1, 1, N, B, Y);
else
{
answer = MAX;
query(1, 1, N, Y, B);
if (answer > N)
printf("-1\n");
else
printf("%d\n", answer);
}
}
return 0;
}


总结

这一题要维护两个最值,要知道一维线段树中左边的点比右边的坐标值小,再在每个点上维护一个最小值即可
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: