zoukankan      html  css  js  c++  java
  • CodeForces 689E Mike and Geometry Problem

    离散化,树状数组,组合数学。

    这题的大致思路和$HDU$ $5700$一样。都是求区间交的问题。可以用树状数组维护一下。

    这题的话只要计算每一个$i$被统计了几次,假设第$i$点被统计了$ans[i]$次,累加和就是答案。

    $ans[i]$就是看$i$点之后有多少个区间右端点,假设有$m$个,那么$ans[i]$就等于$m$个里面选$k$个的方案数。

    因为数据中$L$,$R$范围较大,所以需要先离散化,计算离散化之后的情况,然后再统计离散化之前的情况。

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<set>
    #include<queue>
    #include<stack>
    #include<iostream>
    using namespace std;
    typedef long long LL;
    const double pi=acos(-1.0),eps=1e-6;
    void File()
    {
        freopen("D:\in.txt","r",stdin);
        freopen("D:\out.txt","w",stdout);
    }
    template <class T>
    inline void read(T &x)
    {
        char c=getchar(); x=0;
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) {x=x*10+c-'0'; c=getchar();}
    }
    
    LL mod=1e9+7;
    const int maxn=1200010;
    int n,k;
    LL f[maxn],a[maxn];
    struct X { int L,R; }s[maxn];
    int c[maxn],b[maxn],sz;
    LL ans[maxn];
    
    int lowbit(int x){return x&(-x);}
    int sum(int x)
    {
        int res=0;
        while(x>0) res=res+c[x],x=x-lowbit(x);
        return res;
    }
    void update(int x,int v)
    {
        while(x<=1200000) c[x]=c[x]+v,x=x+lowbit(x);
    }
    
    LL extend_gcd(LL a,LL b,LL &x,LL &y)
    {
        if(a==0&&b==0) return -1;
        if(b==0){x=1;y=0;return a;}
        LL d=extend_gcd(b,a%b,y,x);
        y-=a/b*x;
        return d;
    }
    
    LL mod_reverse(LL a,LL n)
    {
        LL x,y;
        LL d=extend_gcd(a,n,x,y);
        if(d==1) return (x%n+n)%n;
        else return -1;
    }
    
    int get(int x)
    {
        int L=0,R=sz-1,pos=0;
        while(L<=R)
        {
            int mid=(L+R)/2;
            if(b[mid]<x) L=mid+1;
            else if(b[mid]==x) pos=mid,R=mid-1;
            else R=mid-1;
        }
        return pos+1;
    }
    
    bool cmp(X a,X b) { return a.L<b.L; }
    
    int main()
    {
        scanf("%d%d",&n,&k);
        f[0]=1; for(int i=1;i<=400000;i++) f[i]=i*f[i-1]%mod;
        for(int i=k;i<=400000;i++)
        {
            LL fz=f[i]%mod,fm=f[k]*f[i-k]%mod;
            LL ni=mod_reverse(fm,mod);
            a[i]=fz*ni%mod;
        }
    
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&s[i].L,&s[i].R);
            b[sz++]=s[i].L, b[sz++]=s[i].R;
            b[sz++]=s[i].L-1; b[sz++]=s[i].L+1;
            b[sz++]=s[i].R-1; b[sz++]=s[i].R+1;
        }
    
        sort(b,b+sz);
        sort(s+1,s+1+n,cmp);
    
        int h=1;
        for(int i=1;i<=sz;i++)
        {
            while(h<=n&&get(s[h].L)==i)
            {
                update(get(s[h].R),1);
                h++;
            }
            ans[i]=a[sum(1200000)-sum(i-1)];
        }
    
        LL Ans=0;
        for(int i=0;i<sz;)
        {
            int pos=-1;
            for(int j=i;j<sz;j++)
            {
                if(b[j]>b[i]) { pos=j; break; }
            }
            if(pos==-1) { Ans=(Ans+ans[i+1])%mod; break; }
            Ans=(Ans+(b[pos]-b[i])*ans[i+1]%mod)%mod;
            i=pos;
        }
    
        printf("%lld
    ",Ans);
        return 0;
    }
  • 相关阅读:
    注意:MagickReadImageBlob() 引发的问题
    Notepad++ 【自动完成】与【输入时提示函数参数】互相冲突,无奈
    收藏:png8和png24的根本区别
    【物理分辨率】与【逻辑分辨率】
    算法
    算法
    Linux 用户和文件
    Oracle索引技术研究
    Linux Socket
    Linux Socket
  • 原文地址:https://www.cnblogs.com/zufezzt/p/5875975.html
Copyright © 2011-2022 走看看