码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces 689E - Mike and Geometry Problem

时间:2016-07-08 13:30:40      阅读:170      评论:0      收藏:0      [点我收藏+]

标签:

题意:给出你多个区间,在给定的区间中选出至少k区间,算出它们相交后的区间大小。然后算出所有情况的和。

分析:把所有区间叠加起来,然后算出次数tk>=k的子区间的组合数C(tk,k),然后求和。

涉及的知识点:乘法逆元+离散化+(线段树)

代码1:(简单且快且需要空间少且代码短)

/************************************************
Author        :DarkTong
Created Time  :2016/7/8 9:12:58
File Name     :E_3.cpp
*************************************************/

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <cstdlib>
#include <ctime>

#define INF 0x3f3f3f3f
#define esp 1e-9
typedef long long LL;
using namespace std;
const int maxn = 200000 + 10;
const int MOD = 1e9+7;
int l[maxn], r[maxn], sum[maxn*2], rec[maxn*2];
LL fac[maxn];
int quick(LL x, int n)
{
    LL ans=1;
    if(x==0) return 0;
    while(n)
    {
        if(n&1)ans=(ans*x)%MOD;
        x=(x*x)%MOD;
        n>>=1;
    }
    return ans;
}
void init()
{
    fac[0]=1;
    for(int i=1;i<maxn;++i) fac[i]=(fac[i-1]*i)%MOD;
}
int Inv(int n)
{
    return quick(n, MOD-2);
}
LL Cnm(int n, int m)
{
    return fac[n]*(Inv(fac[m]*fac[n-m]%MOD))%MOD;
}

int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    init();
    int n, k, cnt=0;
    scanf("%d%d", &n, &k);
    for(int i=0;i<n;++i)
    {
        scanf("%d%d", &l[i], &r[i]);
        rec[cnt++]=l[i];
        rec[cnt++]=++r[i];
    }
    sort(rec, rec+cnt);
    cnt=unique(rec, rec+cnt)-rec;
    for(int i=0;i<n;++i)
    {
        int t;
        t = lower_bound(rec, rec+cnt, l[i])-rec; sum[t]++;
        t = lower_bound(rec, rec+cnt, r[i])-rec; sum[t]--;
    }
    int tk = sum[0], ans=0;
    for(int i=1;i<cnt;++i)
    {
        if(tk>=k) ans = (ans+Cnm(tk, k)*(rec[i]-rec[i-1])%MOD)%MOD;
        tk += sum[i];
    }
    printf("%d\n", ans);
    return 0;
}

代码2:(线段树-复杂且慢且需要空间多且代码长)

/************************************************
Author        :DarkTong
Created Time  :2016/7/7 21:58:31
File Name     :E_2.cpp
*************************************************/

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <cstdlib>
#include <ctime>

#define INF 0x3f3f3f3f
#define esp 1e-9
typedef long long LL;
using namespace std;
const int maxn = 200000 + 100;
const int MOD = 1e9+7;
struct Node
{
    int l, r, w, f;
}a[maxn*16];
int n, k, l[maxn], r[maxn], tt[maxn*4];
map<int, int> id;

LL fac[maxn];
void init()
{
    fac[0]=1;
    for(int i=1;i<maxn;++i) fac[i]=(fac[i-1]*i)%MOD;
}
LL quick(LL x, int n)
{
    LL ans = 1;
    if(x==0) return 0;
    while(n)
    {
        if(n&1)ans=(ans*x)%MOD;
        x=x*x%MOD;
        n>>=1;
    }
    return ans;
}
LL Inv(LL x)
{
    return quick(x, MOD-2);
}

LL Cnm(LL n, LL m)
{
    LL t = (fac[n]*Inv(fac[m]*fac[n-m]%MOD))%MOD;
    return t;
}

void PushDown(int th)
{
    a[th<<1].w += a[th].w;
    a[th<<1|1].w+=a[th].w;
    a[th].w = 0;
    a[th<<1].f=a[th<<1|1].f=1;
    a[th].f = 0;
}
void Build(int th, int L, int R)
{
    a[th].l=L;
    a[th].r=R;

    a[th].f=a[th].w=0;
    if(L+1==R) return;

    int m=(L+R)/2;
    Build(th<<1, L, m);
    Build(th<<1|1, m, R);
}
void Update(int th, int L, int R)
{
    if(L<=a[th].l&&a[th].r<=R)
    {
        a[th].w++;
        a[th].f=1;
        return;
    }
    if(a[th].f) PushDown(th);
    int m=(a[th].l+a[th].r)/2;

    if(L<m&&m<=R)Update(th<<1, L, m);
    else if(L<m) Update(th<<1, L, R);
    if(L<=m&&m<R)Update(th<<1|1, m, R);
    else if(m<R) Update(th<<1|1, L, R);
}
LL Tra(int th, int L, int R)
{
    if(L+1==R)
    {
        if(a[th].w>=k)return Cnm(a[th].w, k)*(tt[a[th].r]-tt[a[th].l])%MOD;
        else return 0;
    }
    if(a[th].f) PushDown(th);
    int m = (a[th].l+a[th].r)/2;
    LL ans=0;
    ans+=Tra(th<<1, L, m);
    ans+=Tra(th<<1|1, m, R);    
    return ans%MOD;
}

int main()
{
    init();
    scanf("%d%d", &n, &k);
    int tl, tr, cnt=0;
    for(int i=0;i<n;++i)
    {
        scanf("%d%d", &tl, &tr);
        l[i]=tl; r[i]=tr;
        tt[cnt++]=tl; tt[cnt++]=tl+1;
        tt[cnt++]=tr; tt[cnt++]=tr+1;
    }
    //lisanhua
    sort(tt, tt+cnt);
    cnt = unique(tt, tt+cnt)-tt;
    for(int i=0;i<cnt;++i) id[tt[i]]=i;
    Build(1, 0, cnt-1);
    
    for(int i=0;i<n;++i) Update(1, id[l[i]], id[r[i]+1]);
    cout<<Tra(1, 0, cnt-1)<<endl;

    return 0;
}

 

Codeforces 689E - Mike and Geometry Problem

标签:

原文地址:http://www.cnblogs.com/DarkTong/p/5653063.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!