CF D. Buses

这题题意是从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;
}


你可能感兴趣的:(c)