保卫艾尔
来源:互联网 发布: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");}
- 保卫艾尔
- 保卫方案
- 保卫方案
- 保卫方案
- 继续跑步,保卫自己
- "保卫钓鱼岛"进展顺利
- 保卫你的
- 【京东校招笔试】保卫方案
- [编程题] 保卫方案
- 父子对话,你想保卫啥
- 超萌塔防游戏:《保卫萝卜CarrotFantasy》
- 《保卫萝卜》项目实践心得
- 牛客网 编程题 保卫方案
- 保卫国家-需要什么样的理由
- 谁来保卫我们的果实
- 文件加密保卫中小企业信息安全
- Windows 7 防火墙, 计算机的保卫长城
- 《保卫萝卜2》成功背后的思考
- Leetcode——438. Find All Anagrams in a String
- 教师资格证考试大纲
- 2016年年度总结
- FFmpeg 视频转化为bmp图片实例解析
- 爬楼梯
- 保卫艾尔
- QT学习笔记03坐标系统
- 基于Python的爬虫项目一——城市天气
- java使用WebUploader做大文件的分块和断点续传
- 二维码Data Matrix的解码实现(zxing-cpp)
- 重拾java基础(一):java概述总结
- 数据结构实验之链表六:有序链表的建立
- N沟道的Vgs是正的,P沟道的Vgs是负的
- 备忘录模式(行为型)