170125省选模拟赛p3 Times

本文介绍了一种关于视野控制的问题解决方法,通过离线处理和二分查找算法来确定单位在特定时间段内的可见性,适用于类似游戏场景中的视野管理。

Times

问题描述

​ 小 y 作为一名资深的 dotaer,对视野的控制有着深刻的研究。

​ 每个单位在一段特定的时间内会出现在小 y 的视野内,除此之外的时间都在小 y 看不到的地方。在小 y 看来,视野内的单位数量越多,他就越安全,因为这意味着有可能藏在阴影中的单位就越少。

​ 现在,小 y 已经知道了每个单位会在什么时候出现在视野内,他想知道,在一段时间内,总共有多少个单位出现在他的视野内过。

输入格式

​ 第一行有两个整数 n,m,表示一共有 n 个单位,而小 y 有 m 个问题。

​ 接下来 n 行,每行两个数 a,b,表示这个单位 a 秒时出现在小 y 的视野内,出现了 b 秒。

​ 接下来 m 行,每行两个整数 x,y,表示从 x 秒开始,经过 y 秒,其中有多少个单位出现过。

输出格式

​ m 行,即对于小 y 提出的每个问题的答案。

Input Samples 1

​ 3 2
​ 2 5
​ 0 10
​ 5 8
​ 0 6
​ 8 2

Output Samples 1

​ 3
​ 2

Input Samples 2

​ 1 2
​ 0 10
​ 9 1
​ 10 1

Output Sample 2

​ 1
​ 0

题解

​ 这题做法貌似挺多的。在考场上发现和校门外的树3十分相似。对于每一个询问L~R,答案即为

{R}{L}
又由于所有询问都在修改之后,所以离线处理即可,一开始还以为需要树状数组(写了100多行然后幡然醒悟),其实只需要将左端点和右端点分别排序然后二分查找即可,对于0.5s的时限压力不大。
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;

const int N = 200000 + 10;
int L[N], R[N];
int n, m;

inline void in(int& x);

void init(){
    in(n), in(m);
    for(int i = 1; i <= n; i++){
        in(L[i]);
        in(R[i]); R[i] += L[i] - 1;
    }
    sort(L+1, L+n+1);
    sort(R+1, R+n+1);
}
int lbd1(int x){
    int l, r, m;
    l = 1, r = n;
    if(x < L[l]) return 0;
    if(x >= L[r]) return n;
    while(l < r){
        m = (l + r) >> 1;
        if(L[m] <= x && L[m+1] > x) return m;
        if(L[m] <= x) l = m + 1;
        else r = m;
    }
    return l;
}
int lbd2(int x){
    int l, r, m;
    l = 1, r = n;
    if(x < R[l]) return 0;
    if(x >= R[r]) return n;
    while(l < r){
        m = (l + r) >> 1;
        if(R[m] <= x && R[m+1] > x) return m;
        if(R[m] <= x) l = m + 1;
        else r = m;
    }
    return l;
}
void work(){
    int l, r;
    for(int i = 1; i <= m; i++){
        scanf("%d%d", &l, &r);
        r = l + r - 1;
        printf("%d\n", lbd1(r) - lbd2(l-1));
    }
}
int main(){
    freopen("times.in", "r", stdin);
    freopen("times.out", "w", stdout);
    init();
    work();
}

inline void in(int& x){
    x = 0; int f = 1;
    char c; c = getchar();
    while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while(c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值