这题题意是从0到0=<n<=10^9有n个汽车站,现在有0<=m<=10^5辆车,告诉你每辆车经过的站,你只要上了这一辆车,就必须坐到这辆车的终点站,才能下车,求你到第n个车站有多少种乘车方法。设定状态dp[i]表示到达第i个站的乘车方法,这样好像不行n<10^9,显然可以发现状态转移就是每辆车的经过车站都可以上车,那么总站就可以由这个车其他的车站转移过来,但是由于你只能在终点站下车,所以你上车的地方也只能是下车的地方,下车的地方就10^5可以存的下,显然dp[i]=sum{dp[k]}k表示这辆车经过的站,状态的转移要求就是要排好序,前面的状态一定要先统计,这是必需的,这里你会发现是对一连续区间求和,就用树状数组来实现吧,不过要离散化,我之前写个离散化用了二分查找,开了几个数组写乱了,花了不少时间纠错,后面用map感觉方便很多,代码也变少了,不过map尽量少用,容易超时;
#include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<cmath> #include<iostream> #include<map> using namespace std; const long long N=1000000000+7; long long c[200050],d[200050],dp[200050],maxn,len; struct qu { long long x,y; }q[100005]; bool cmp(qu a,qu b) { if(a.y==b.y) return a.x<b.x; else return a.y<b.y; } int bit(int n){ return n&-n; } long long count(int n) { long long ans=0; while(n) { ans+=c[n]; ans=(ans+N)%N; n-=bit(n); } return ans; } void update(int n,long long k) { while(n<=maxn) { c[n]+=k; c[n]=(c[n]+N)%N; n+=bit(n); } } int main() { int n,m,i,j,k=1,flag=0; map<long ,long> mp; while(scanf("%d%d",&n,&m)!=EOF) { memset(dp,0,sizeof(dp)); memset(d,0,sizeof(d)); memset(c,0,sizeof(c)); mp.clear(); k=1; for(i=0;i<m;i++) { scanf("%d%d",&q[i].x,&q[i].y); d[k++]=q[i].x; d[k++]=q[i].y; } d[k++]=n; len=k; sort(d,d+len); flag=1; for(i=0;i<len;i++) { if(mp[d[i]]==0) mp[d[i]]=flag++; } maxn=flag; sort(q,q+m,cmp); if(d[0]==0) update(1,1); for(i=0;i<m;i++) { int x=mp[q[i].x]; int y=mp[q[i].y]; int sum=count(y-1)-count(x-1); dp[y]+=sum; dp[y]=(dp[y]+N)%N; update(y,sum); } printf("%d\n",dp[mp[d[len-1]]]); } return 0; }