UPCOJ-5531 [COCI 2017-2018-1] - Deda - 线段树 + 二分

链接:

http://exam.upc.edu.cn/problem.php?id=5531

题目:

题目描述

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 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.

输入

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.

输出

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

样例输入

3 4
M 10 3
M 5 1
D 20 2
D 5 1

样例输出

3
1

题意:

  有一辆车上有n个小孩,年龄为1~n,然后q个询问,M X A代表在第X站时年龄为A的小孩会下车,D Y B代表询问年龄大于等于B且在第Y站(包含第Y站)以前下车的年龄最小的小孩,如果不存在,则输出-1


思路:

  写一个长度为n的线段树,min[i]代表年龄为i的孩子在第min[i]站下车,初始为无穷大。这样在询问的时候就只需要关心[B, n]这个区间,考虑二分答案,我们通过线段树维护某个年龄段里所有孩子的最早在第几站下的车,这样就可以通过查询区间最小值并和Y进行比较来判断是否合法,合法的话继续向左二分找到最小的那个孩子即可。


实现:

#include <bits/stdc++.h>
#define lson u << 1
#define rson u << 1 | 1
const int maxn = int(1e6) + 7;
int min[maxn], n, q, a, b;
char op;
void pushup(int u) { min[u] = std::min(min[lson], min[rson]); }
void update(int aim, int val, int l = 1, int r = n, int u = 1) {
    if (l == r) min[u] = val;
    else {
        int mid = l + r >> 1;
        if (aim <= mid) update(aim, val, l, mid, lson);
        else update(aim, val, mid + 1, r, rson);
        pushup(u);
    }
}
int query(int begin, int end, int l = 1, int r = n, int u = 1) {
    if (begin <= l && r <= end) return min[u];
    int mid = l + r >> 1;
    if (end <= mid) return query(begin, end, l, mid, lson);
    else if (begin > mid) return query(begin, end, mid + 1, r, rson);
    return std::min(query(begin, end, l, mid, lson), query(begin, end, mid + 1, r, rson));
}
int main() {
//    freopen("in.txt", "r", stdin);
    memset(min, 0x7f, sizeof(min));
    scanf("%d%d", &n, &q);
    while (q--) {
        scanf(" %c%d%d", &op, &a, &b);
        if (op == 'M') update(b, a);
        else {
            int l = b, r = n, mid, ans = -1;
            while (l <= r) {
                mid = l + r >> 1;
                if (query(l, mid) <= a) r = mid - 1, ans = mid;
                else l = mid + 1;
            }
            printf("%d\n", ans);
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值