跳方格(离散化+差分)

跳方格 (lattice)

时间限制: 1 Sec  内存限制: 128 MB

题目描述

有一个长长的走廊,巨神 ctt 把它分成m方格,从左到右编号为1,2,...,m。

有一天,巨神 ctt 得到了n个蹦床,他把这些蹦床放在方格里,他在编号为1的方格里放了一个蹦床,在编号为2,3,...,m-1的方格中放置了n-1个蹦床(一个方格只能放一个蹦床)。

巨神 ctt 估算了自己的跳远水平和蹦床的弹性,知道了他从第i个蹦床跳跃最多可以跳过li个方格(若这个蹦床放置的方格编号为k,则他最多能跳到编号为k+li的方格里,l1表示从编号为1的方格里的蹦床跳跃最可以跳过l1个方格),他开始计算从编号为1的方格,从左向右在蹦床上跳跃,最终到达编号为m的方格上,这样跳跃的方式有多少种。

巨神 ctt 非常生气,因为他直接秒出了答案,所以他用这繁杂的统计来考考你,但你的结果可以对109+7取模。

输入

第一行三个正整数n,m,l1,表示蹦床的个数、方格的个数和从编号为1的方格里的蹦床跳跃最可以跳过的方格数。
接下来n-1行,每行两个正整数,第i行的两个正整数分别表示第i个蹦床所在方格的编号和从第i个蹦床跳跃最多可以跳过的方格数。

输出

仅一行一个整数表示答案。

样例输入

【样例1】
3 5 3
2 1
4 1
【样例2】
5 7 2
2 2
4 1
5 2
6 1

样例输出

【样例1】
1
【样例2】
2
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int maxn=1e6+10;
struct node{
    int p,l;
}a[maxn];
bool operator<(const node &a,const node &b) {
    return a.p < b.p;
}
ll f[maxn];
int n,m,p,ans;
int fl(int x) {
    int res = -1;
    int l = 2, r = n + 1;
    while (l <= r) {
        int mid = (l + r) / 2;
        if (a[mid].p >= x) {
            res = mid;
            r = mid - 1;
        } else l = mid + 1;
    }
    return res;
}
int fr(int x) {
    int res = -1;
    int l = 2, r = n + 1;
    while (l <= r) {
        int mid = l + r >> 1;
        if (a[mid].p <= x) {
            res = mid;
            l = mid + 1;
        } else r = mid - 1;
    }
    return res;
}
int main() {
    scanf("%d%d%d", &n, &m, &p);
    for (int i = 2; i <= n; i++)
        scanf("%d%d", &a[i].p, &a[i].l);
    sort(a + 2, a + n + 1);
    a[1].p = 1;
    a[1].l = p;
    a[n + 1].p = m;
    f[1] = 1;
    f[2] = -1;
    for (int i = 1; i <= n; i++) {
        ans = (ans + f[i]) % mod;
        int l = fl(a[i].p + 1), r = fr(a[i].p + a[i].l);
        if (~l && ~r) {
            f[l] = (f[l] + ans) % mod;
            f[r + 1] = (f[r + 1] - ans + mod) % mod;
        }
    }
    printf("%lld\n", (ans + f[n + 1]) % mod);
    return 0;
}

                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值