Description
数轴上 0 0 ~每点都有一个公交站,有 m m 趟公交车,第趟公交车从 si s i 站开往 ti t i 站,可以从 si s i ~ ti−1 t i − 1 的任一站上车,但是只能从 ti t i 下车,问从 0 0 到的路径数
Input
第一行两个整数 n,m n , m ,之后 m m 行每行输入两个整数 (1≤n≤109,0≤m≤105,0≤si<ti≤n) ( 1 ≤ n ≤ 10 9 , 0 ≤ m ≤ 10 5 , 0 ≤ s i < t i ≤ n )
Output
输出方案数,结果模 109+7 10 9 + 7
Sample Input
2 2
0 1
1 2
Sample Output
1
Solution
dp[i] d p [ i ] 表示从 0 0 到的方案数,把所有公交线路按 ti t i 升序排,同样 ti t i 的按 si s i 升序排,考虑 si→ti s i → t i 这条线路时,之前的线路终点站必然在 ti t i 前,我们要找的是所有终点站介于 si,ti s i , t i 之间的路线,二分找到第一条终点站不小于 si s i 的线路编号为 j j ,那么有转移,记 dp d p 前缀和数组为 sum s u m ,那么有 dp[i]=sum[i−1]−sum[j−1] d p [ i ] = s u m [ i − 1 ] − s u m [ j − 1 ] ,以此转移即可,答案即为 ∑ti=ndp[i] ∑ t i = n d p [ i ] ,时间复杂度 O(mlogm) O ( m l o g m )
Code
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const int INF=0x3f3f3f3f,maxn=100005;
#define mod 1000000007
#define s second
#define t first
int n,m,sum[maxn];
P a[maxn];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)scanf("%d%d",&a[i].s,&a[i].t);
sort(a+1,a+m+1);
sum[0]=1;
int ans=0;
for(int i=1;i<=m;)
{
int k;
for(k=i;k<=m&&a[k].t==a[i].t;k++)
{
int pos=lower_bound(a,a+i,P(a[k].s,0))-a;
int temp;
if(pos>0)temp=(sum[i-1]-sum[pos-1]+mod)%mod;
else temp=sum[i-1];
sum[k]=(sum[k-1]+temp)%mod;
if(a[k].t==n)ans=(ans+temp)%mod;
//printf("k=%d dp=%d\n",k,dp[k]);
}
i=k;
}
printf("%d\n",ans);
return 0;
}