!!!
时间限制: 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个蹦床跳跃最多可以跳过的方格数。
输出
仅一行一个整数表示答案。
样例输入 Copy
【样例1】 3 5 3 2 1 4 1 【样例2】 5 7 2 2 2 4 1 5 2 6 1
样例输出 Copy
【样例1】 1 【样例2】 2
提示
中文题意
首先看到n <= 1e6,m<=1e8,绝对是对n操作,而不是对m进行操作
考虑如何对n进行操作?
发现,只有有蹦床的点才会对答案有贡献,那么有蹦床的点不就这n个点?
如何才能不考虑到数值问题呢?
离散化通常是将问题转换为只与大小有关系的问题,所以可以这么考虑。
假设x 可以跳到 x+y,那么x对 [x+1,x+y]有贡献,那么[x+1,x+y]有哪些点就变成了只考虑大小的问题
所以此题也就可以解决了 —— 线段树与树状数组都可
但是会被卡超时(如果是用线段树或者树状数组) 或许常数太大?
考虑差分数组,但是差分数组有不能在线(边修改边查询)
但是会发现这个过程,只会查询当前位置向后的位置,而不查询当前位置之前的位置,所以差分数组完全可以!
之后就卡过啦!
/*** keep hungry and calm CoolGuang!***/
#pragma GCC optimize(3)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair pp;
const ll INF=1e17;
const int Maxn=1e6+10;
const int maxn =1e6+10;
const int mod= 1e9+7;
const int Mod = 1e6+7;
///const double eps=1e-10;
const int S = 1000;
inline bool read(ll &num)
{char in;bool IsN=false;
in=getchar();if(in==EOF) return false;while(in!='-'&&(in<'0'||in>'9')) in=getchar();if(in=='-'){ IsN=true;num=0;}else num=in-'0';while(in=getchar(),in>='0'&&in<='9'){num*=10,num+=in-'0';}if(IsN) num=-num;return true;}
ll n,m,p;
struct node{
int pos,l;
}q[maxn];
bool operator<(node a,node b){
return a.pos < b.pos;
}
int check_l(int x){///大于等于l的第一个位置
int ans = -1;
int l = 2,r = n+1;
while(l<=r){
int mid = (l+r)/2;
if(q[mid].pos >= x){
ans = mid;
r = mid-1;
}else l = mid+1;
}
return ans;
}
int check_r(int x){
int ans = -1;
int l =2,r = n+1;
while(l<=r){
int mid = (l+r)/2;
if(q[mid].pos <= x){
ans = mid;
l = mid+1;
}else r = mid-1;
}
return ans;
}
ll dp[maxn];
ll f[maxn];
int main()
{
read(n);read(m);read(p);
for(int i=2;i<=n;i++)
scanf("%d%d",&q[i].pos,&q[i].l);
sort(q+2,q+n+1);
dp[1] = 1;
q[1].pos = 1;
q[1].l = p;
q[n+1].pos = m;
f[1] = 1;
f[2] = -1;
ll ans = 0;
for(int i=1;i<=n;i++){
ans = (ans + f[i])%mod;
int l = check_l(q[i].pos+1),r = check_r(q[i].pos+q[i].l);
if(~l&&~r){
f[l] = (f[l] + ans)%mod;
f[r+1] = (f[r+1] - ans%mod+mod)%mod;
}
}
printf("%lld\n",(ans + f[n+1])%mod);
return 0;
}