hatredvirus

导航

 

题目背景

zeromaker 是个手残,但是他喜欢玩东方 project,ex 什么的最喜欢了

题目描述

zeromaker 对弹幕的视野控制有着深刻的研究。 每个弹幕在一段特定的时间内会出现在 zeromaker 的视野内,除此之外的时间都在 zeromaker 看不到的地方。在 zeromaker 看来,视野内的弹幕数量越多,图就越难,因为这意味着 @#¥%。 现在,zeromaker 想要评测这张图的难度,他已经知道了每个弹幕会在什么时候出现在视野内,他想知道,在一段时间内,总共有多少个弹幕出现在他的视野内过。

输入格式

第一行有两个整数 n , m ,表示一共有 n 个弹幕,而 zeromaker 有 m 个问题。

接下来 n 行,每行两个数 ab,表示这个弹幕a 秒时出现在 zeromaker 的视野内,出现了 b 秒。 接下来 m 行,每行两个整数 x , y ,表示从 x 秒开始,经过 y秒,其中有多少个弹幕出现过。

注意:查询区间为左闭右闭,弹幕出现区间为左开右开。

输出格式

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

输入输出样例

输入 #1             输出#1  
3 2            3
2 5            2
0 10
5 8
0 6
8 2
输入#2              输出#2    
1 2           1
0 10          0
9 1
10 1


解题思路:
分两块来看:1.弹幕出现区间 2.查询区间

1.弹幕出现区间:
由题意,弹幕出现区间为开区间,若a秒出现在视野中,出现了b秒,则能看到弹幕的第一秒为a,最后一秒为a+b-1
如图,假设从左进入视野,向右滚动,第a+b秒为:

所以,可以设定两个数组 l、r,数组l储存所有弹幕出现的时间(即出现在左端的时间),数组r储存所有弹幕出现的最后一秒(即出现在右端的时间)

再用sort函数将两个数组分别排序,可以得到依次、分别得到出现在左端和右端的时间。

2.查询区间
由题意,查询区间为闭区间,所以无需减一,查询弹幕的第一秒为a,最后一秒为a+b
确定弹幕出现区间和查询区间后,可以用两次lower_bound函数得到结果
设定查询的第一秒为l2,持续r2秒,即查询最后一秒为l2+r2
首先在数组l中 用lower_bound(l,l+n,r2)-l 即在l数组中返回大于等于r2的第一个值的位置①
随后在数组r中 用lower_bound(r,r+n,l2)-r 即在r数组中返回大于等于l2的第一个值的位置②
最后由①-②,便能得到在该段时间内总共出现的弹幕数量。

代码:
#include <iostream>
#include <algorithm>

using namespace std;

int main()
{
    int n,m,i,l[100001],r[100001];//l[i]出现,r[i]最后出现的时间
    cin>>n>>m;
    for(i=0;i<n;i++)
    {
        cin>>l[i]>>r[i];
        r[i]=l[i]+r[i]-1;//开区间,减一
    }
    sort(l,l+n);
    sort(r,r+n);//分别进行排序,所有的出现时间和最后时间按顺序
    for(i=0;i<m;i++)
    {
        int l2,r2,s;
        cin>>l2>>r2;
        r2=l2+r2;//闭区间,不用减一
        s=lower_bound(l,l+n,r2)-l;//在所有弹幕出现时间里返回大于等于r2的一个值的位置
        s-=lower_bound(r,r+n,l2)-r;//上面的数减去 弹幕最后出现的时间里大于等于l2的第一个值的位置
        cout<<s<<endl;
    }
    return 0;
}

 

 
posted on 2022-04-25 18:39  HatredVirus  阅读(28)  评论(0编辑  收藏  举报