保卫艾尔

来源:互联网 发布:ghost软件有windows版 编辑:程序博客网 时间:2024/04/27 18:58

题目描述

凯莱克斯研制出的新防御矩阵系统的建立方式是这样的:他用艾尔上的 n座水晶塔为基础建立多层防御矩阵,如果将艾尔视为一个 直角坐标系,则每座水晶塔都有一个坐标(xi,yi) 。
一层防御矩阵是一个四边形,四边形的四个顶点都是一座水晶塔,而且四边形两条对角线分别平行于x 轴和y 轴。两条对角线的交 点为防御矩阵的中心。中心必须位于防御矩阵的内部,同时也不能位于四边形的边上(即该四边形是一个严格的凸四边形)。注 意,防御矩阵的中心不一定有水晶塔。
一个防御矩阵系统由多层防御矩阵组成,一个系统内的所有的防御矩阵都拥有相同的中心,且任意两个四边形不能相交。现在,凯 莱克斯想让你帮他计算大主教给他的三个问题:
1. 如果把层数最多的防御矩阵系统称为最优系统,那最优系统有多少层防御矩阵?
2. 有多少个地点可以作为最优系统的中心?
3. 有多少种建立最优系统的方案?
当然如果你觉得这些问题比较难可以先回答其中的一个或者两个。

扫描线

我们用扫描线做,比如对着x坐标扫。
用线段树维护,叶子表示一个y坐标在扫描线左的点数与在扫描线右的点数的最小值,以及对应组合数。而区间维护最大值,最大值个数及对应组合数的和。
中心要么建点上要么建两点中间,考虑后者枚举一个点,那么得到上面那个点,于是要对一个区间做询问,用线段树获得。
这可以解决第一问,但是如果左右被上下所限制(上下可拓展过小),取出的个数及组合数不能用。
因此可以两个坐标反过来再扫一遍。
关于两边拓展相同,在其中一次扫考虑另外一次不考虑即可。
线段树的询问最好把三个值的询问打在一起。

#include<cstdio>#include<algorithm>#define fo(i,a,b) for(i=a;i<=b;i++)#define fd(i,a,b) for(i=a;i>=b;i--)using namespace std;typedef long long ll;const int maxn=500000+10,mo=1000000007;struct dong{    int x,y;} a[maxn],aa[maxn];int tree[maxn*4],cnt[maxn*4],num[maxn*4],sum[maxn*4],wz[5000+10][5000+10];int cntx[maxn],cnty[maxn],b[maxn],fac[maxn],inv[maxn];int d[maxn],c[maxn],e[maxn];int i,j,k,l,r,t,n,m,ans1,ans2,ans3,czy,tx,ty,p;int an1,an2,an3;int read(){    int x=0,f=1;    char ch=getchar();    while (ch<'0'||ch>'9'){        if (ch=='-') f=-1;        ch=getchar();    }    while (ch>='0'&&ch<='9'){        x=x*10+ch-'0';        ch=getchar();    }    return x*f;}int quicksortmi(int x,int y){    if (!y) return 1;    int t=quicksortmi(x,y/2);    t=(ll)t*t%mo;    if (y%2) t=(ll)t*x%mo;    return t;}bool cmp(dong a,dong b){    return a.x<b.x||a.x==b.x&&a.y<b.y;}bool cmp2(dong a,dong b){    return a.y<b.y||a.y==b.y&&a.x<b.x;}int qry1(int p,int l,int r,int a,int b){    if (a>b) return 0;    if (l==a&&r==b) return tree[p];    int mid=(l+r)/2;    if (b<=mid) return qry1(p*2,l,mid,a,b);    else if (a>mid) return qry1(p*2+1,mid+1,r,a,b);    else return max(qry1(p*2,l,mid,a,mid),qry1(p*2+1,mid+1,r,mid+1,b));}int qry2(int p,int l,int r,int a,int b){    if (a>b) return 0;    if (l==a&&r==b) return num[p];    int mid=(l+r)/2;    if (b<=mid) return qry2(p*2,l,mid,a,b);    else if (a>mid) return qry2(p*2+1,mid+1,r,a,b);    else{        int j=qry1(p*2,l,mid,a,mid),k=qry1(p*2+1,mid+1,r,mid+1,b);        if (j>k) return qry2(p*2,l,mid,a,mid);        else if (j<k) return qry2(p*2+1,mid+1,r,mid+1,b);        else return (qry2(p*2,l,mid,a,mid)+qry2(p*2+1,mid+1,r,mid+1,b))%mo;    }}int qry3(int p,int l,int r,int a,int b){    if (a>b) return 0;    if (l==a&&r==b) return sum[p];    int mid=(l+r)/2;    if (b<=mid) return qry3(p*2,l,mid,a,b);    else if (a>mid) return qry3(p*2+1,mid+1,r,a,b);    else{        int j=qry1(p*2,l,mid,a,mid),k=qry1(p*2+1,mid+1,r,mid+1,b);        if (j>k) return qry3(p*2,l,mid,a,mid);        else if (j<k) return qry3(p*2+1,mid+1,r,mid+1,b);        else return (qry3(p*2,l,mid,a,mid)+qry3(p*2+1,mid+1,r,mid+1,b))%mo;    }}void qry(int p,int l,int r,int a,int b){    if (a>b) return;    if (l==a&&r==b){        if (tree[p]>an1){            an1=tree[p];            an2=num[p];            an3=sum[p];        }        else if (tree[p]==an1){            an2=(an2+num[p])%mo;            an3=(an3+sum[p])%mo;        }        return;    }    int mid=(l+r)/2;    if (b<=mid) qry(p*2,l,mid,a,b);    else if (a>mid) qry(p*2+1,mid+1,r,a,b);    else{        qry(p*2,l,mid,a,mid);        qry(p*2+1,mid+1,r,mid+1,b);    }}int C(int n,int m){    if (n<m) return 0;    return (ll)fac[n]*inv[m]%mo*inv[n-m]%mo;}void change(int p,int l,int r,int a){    if (l==r){        cnt[p]++;        tree[p]=min(cnt[p],cnty[l]-cnt[p]);        num[p]=1;        sum[p]=(ll)C(cnt[p],tree[p])*C(cnty[l]-cnt[p],tree[p])%mo;        return;    }    int mid=(l+r)/2;    if (a<=mid) change(p*2,l,mid,a);else change(p*2+1,mid+1,r,a);    tree[p]=max(tree[p*2],tree[p*2+1]);    if (tree[p*2]>tree[p*2+1]) num[p]=num[p*2],sum[p]=sum[p*2];    else if (tree[p*2]<tree[p*2+1]) num[p]=num[p*2+1],sum[p]=sum[p*2+1];    else num[p]=(num[p*2]+num[p*2+1])%mo,sum[p]=(sum[p*2]+sum[p*2+1])%mo;}void brute(){    k=1;    fo(i,1,tx){        t=0;        fo(j,1,ty){            l=cntx[i]-t;            if (i==a[k].x&&j==a[k].y) l-=wz[i][j];            r=cnty[j]-cnt[j];            if (i==a[k].x&&j==a[k].y) r-=wz[i][j];            p=min(l,min(r,min(cnt[j],t)));            if (p>ans1){                ans1=p;                ans2=1;                ans3=(ll)C(t,p)*C(l,p)%mo*C(cnt[j],p)%mo*C(r,p)%mo;            }            else if (p==ans1){                ans2=(ans2+1)%mo;                ans3=(ans3+(ll)C(t,p)*C(l,p)%mo*C(cnt[j],p)%mo*C(r,p)%mo)%mo;            }            while (k<=n&&i==a[k].x&&j==a[k].y){                cnt[j]++;                t++;                k++;            }        }    }    printf("%d",ans1);    if (czy>=2) printf(" %d",ans2);    if (czy==3) printf(" %d",ans3);    printf("\n");}void clear(){    int i;    fo(i,1,ty*4) tree[i]=cnt[i]=num[i]=sum[i]=0;}int main(){    freopen("aiur.in","r",stdin);freopen("aiur.out","w",stdout);    n=read();czy=read();    fo(i,1,n) a[i].x=read(),a[i].y=read();    fo(i,1,n) b[i]=a[i].x;    sort(b+1,b+n+1);    tx=unique(b+1,b+n+1)-b-1;    fo(i,1,n) a[i].x=lower_bound(b+1,b+tx+1,a[i].x)-b;    fo(i,1,n) b[i]=a[i].y;    sort(b+1,b+n+1);    ty=unique(b+1,b+n+1)-b-1;    fo(i,1,n) a[i].y=lower_bound(b+1,b+ty+1,a[i].y)-b;    fo(i,1,n) cntx[a[i].x]++,cnty[a[i].y]++;    /*if (n<=5000){        fo(i,1,n) wz[a[i].x][a[i].y]++;    }*/    fac[0]=1;    fo(i,1,n) fac[i]=(ll)fac[i-1]*i%mo;    inv[n]=quicksortmi(fac[n],mo-2);    fd(i,n-1,0) inv[i]=(ll)inv[i+1]*(i+1)%mo;    /*if (n<=5000){        brute();        return 0;    }*/    //sort(a+1,a+n+1,cmp);    fo(i,1,ty) d[i]=0;    fo(i,1,n) d[a[i].y]++;    fo(i,1,ty) d[i]+=d[i-1];    fd(i,n,1) c[d[a[i].y]--]=i;    fo(i,1,tx) d[i]=0;    fo(i,1,n) d[a[i].x]++;    fo(i,1,tx) d[i]+=d[i-1];    fd(i,n,1) e[d[a[c[i]].x]--]=c[i];    fo(i,1,n) aa[i].x=a[e[i]].x,aa[i].y=a[e[i]].y;    fo(i,1,n) a[i].x=aa[i].x,a[i].y=aa[i].y;    l=0;    fo(i,1,n){        l++;        if (i<n&&a[i].x!=a[i+1].x) l=0;        if (i<n&&a[i].x==a[i+1].x){            an1=an2=an3=0;            qry(1,1,ty,a[i].y+1,a[i+1].y-1);            t=an1;            //t=qry1(1,1,ty,a[i].y+1,a[i+1].y-1);            if (l<cntx[a[i].x]-l) r=l;else r=cntx[a[i].x]-l;            //r=min(l,cntx[a[i].x]-l);            if (t<=r){                if (t>ans1){                    ans1=t;                    ans2=an2;                    ans3=(ll)an3*C(l,t)%mo*C(cntx[a[i].x]-l,t)%mo;                }                else if (t==ans1){                    ans2=(ans2+an2)%mo;                    ans3=(ans3+(ll)an3*C(l,t)%mo*C(cntx[a[i].x]-l,t)%mo)%mo;                }            }        }        change(1,1,ty,a[i].y);    }    clear();    fo(i,1,n) cntx[a[i].x]--,cnty[a[i].y]--;    fo(i,1,n) swap(a[i].x,a[i].y);    swap(tx,ty);    fo(i,1,n) cntx[a[i].x]++,cnty[a[i].y]++;    //sort(a+1,a+n+1,cmp);    fo(i,1,ty) d[i]=0;     fo(i,1,n) d[a[i].y]++;    fo(i,1,ty) d[i]+=d[i-1];    fd(i,n,1) c[d[a[i].y]--]=i;    fo(i,1,tx) d[i]=0;    fo(i,1,n) d[a[i].x]++;    fo(i,1,tx) d[i]+=d[i-1];    fd(i,n,1) e[d[a[c[i]].x]--]=c[i];    fo(i,1,n) aa[i].x=a[e[i]].x,aa[i].y=a[e[i]].y;    fo(i,1,n) a[i].x=aa[i].x,a[i].y=aa[i].y;    l=0;    fo(i,1,n){        l++;        if (i<n&&a[i].x!=a[i+1].x) l=0;        if (i<n&&a[i].x==a[i+1].x){            an1=an2=an3=0;            qry(1,1,ty,a[i].y+1,a[i+1].y-1);            t=an1;            //t=qry1(1,1,ty,a[i].y+1,a[i+1].y-1);            if (l<cntx[a[i].x]-l) r=l;else r=cntx[a[i].x]-l;            //r=min(l,cntx[a[i].x]-l);            if (t<r){                if (t>ans1){                    ans1=t;                    ans2=an2;                    ans3=(ll)an3*C(l,t)%mo*C(cntx[a[i].x]-l,t)%mo;                }                else if (t==ans1){                    ans2=(ans2+an2)%mo;                    ans3=(ans3+(ll)an3*C(l,t)%mo*C(cntx[a[i].x]-l,t)%mo)%mo;                }            }        }        change(1,1,ty,a[i].y);    }    l=0;    fo(i,1,n) cnt[i]=0;    fo(i,1,n){        l++;        t=min(l-1,min(cnt[a[i].y],min(cnty[a[i].y]-cnt[a[i].y]-1,cntx[a[i].x]-l)));        if (t>ans1){            ans1=t;            ans2=1;            ans3=(ll)C(l-1,t)%mo*C(cnt[a[i].y],t)%mo*C(cnty[a[i].y]-cnt[a[i].y]-1,t)%mo*C(cntx[a[i].x]-l,t)%mo;        }        else if (t==ans1){            ans2=(ans2+1)%mo;            ans3=(ans3+(ll)C(l-1,t)%mo*C(cnt[a[i].y],t)%mo*C(cnty[a[i].y]-cnt[a[i].y]-1,t)%mo*C(cntx[a[i].x]-l,t)%mo)%mo;        }        cnt[a[i].y]++;        if (i<n&&a[i].x!=a[i+1].x) l=0;    }    printf("%d",ans1);    if (czy>=2) printf(" %d",ans2);    if (czy==3) printf(" %d",ans3);    printf("\n");}
0 0
原创粉丝点击