Codeforces Round #361 (Div. 2)E. Mike and Geometry Problem

来源:互联网 发布:i淘宝网首页 编辑:程序博客网 时间:2024/05/18 22:09

链接:http://codeforces.com/contest/689/problem/E

题意:给定n条线段[l,r],求所有的k条线段相交的部分有多少个整数点。

分析:直接C(n,k)是不可能的,我们换个角度求每个点会被统计多少次,那么设有x条线段会覆盖这个点那么这个点就会被统计C(x,k)次咯,我们O(n)将这n条线段覆盖在线段上,然后计数即可。

代码:

#include<map>#include<set>#include<cmath>#include<queue>#include<bitset>#include<math.h>#include<cstdio>#include<vector>#include<string>#include<cstring>#include<iostream>#include<algorithm>#pragma comment(linker, "/STACK:102400000,102400000")using namespace std;const int N=200010;const int MAX=1000000100;const int mod=100000000;const int MOD1=1000000007;const int MOD2=1000000009;const double EPS=0.00000001;typedef long long ll;const ll MOD=1000000007;const int INF=1000000010;const double pi=acos(-1.0);typedef double db;typedef unsigned long long ull;int d[4*N],x[N],y[N],f[4*N],w[4*N];ll F[4*N];ll qpow(ll a,ll b) {    ll ret=1;    while (b) {        if (b&1) ret=ret*a%MOD;        a=a*a%MOD;b>>=1;    }    return ret;}int main(){    int i,h,n,k,l,r,g=0,mx=-INF;    ll ans=0;    scanf("%d%d", &n, &k);    for (i=1;i<=n;i++) {        scanf("%d%d", &x[i], &y[i]);        d[++g]=x[i];d[++g]=y[i];        d[++g]=x[i]+1;d[++g]=y[i]+1;        mx=max(mx,max(x[i],y[i]));    }    d[++g]=mx+1;    sort(d+1,d+g+1);    h=unique(d+1,d+g+1)-(d+1);    memset(f,0,sizeof(f));    for (i=1;i<=n;i++) {        l=lower_bound(d+1,d+h+1,x[i])-d;        r=lower_bound(d+1,d+h+1,y[i])-d;        f[l]++;f[r+1]--;        w[l]=x[i];w[r]=y[i];        w[lower_bound(d+1,d+h+1,x[i]+1)-d]=x[i]+1;        w[lower_bound(d+1,d+h+1,y[i]+1)-d]=y[i]+1;    }    g=lower_bound(d+1,d+h+1,mx+1)-d;    w[g]=mx+1;    for (i=2;i<=h;i++) f[i]+=f[i-1];    memset(F,0,sizeof(F));F[k]=1;    for (i=k+1;i<=2*n;i++) F[i]=((F[i-1]*i%MOD)*qpow(i-k,MOD-2))%MOD;    for (i=1;i<h;i++) ans=(ans+((w[i+1]-w[i])*F[f[i]])%MOD)%MOD;    printf("%I64d\n", (ans+MOD)%MOD);    return 0;}


0 0
原创粉丝点击