CCF 201609-5 祭坛
Posted shenben
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CCF 201609-5 祭坛相关的知识,希望对你有一定的参考价值。
问题描述
试题编号: | 201609-5 |
试题名称: | 祭坛 |
时间限制: | 2.0s |
内存限制: | 256.0MB |
问题描述: |
问题描述
在遥远的Dgeak大陆,生活着一种叫做Dar-dzo-nye的怪物。每当这种怪物降临,人们必须整夜对抗怪物而不能安睡。为了乞求这种怪物不再降临,人们决定建造祭坛。
Dgeak大陆可以看成一个用平面直角坐标系表示的巨大平面。在这个平面上,有 n 个Swaryea水晶柱,每个水晶柱可以用一个点表示。 如果 4 个水晶柱依次相连可以构成一个四边形,满足其两条对角线分别平行于 x 轴和 y 轴,并且对角线的交点位于四边形内部(不包括边界),那么这 4 个水晶柱就可以建立一个结界。其中,对角线的交点称作这个结界的中心。 例如下左图中,水晶柱 ABCD 可以建立一个结界,其中心为 O。 为了起到抵御Dar-dzo-nye的最佳效果,人们会把祭坛修建在最多层结界的保护中。其中不同层的结界必须有共同的中心,这些结界的边界不能有任何公共点,并且中心处也不能有水晶柱。这里共同中心的结界数量叫做结界的层数。 为了达成这个目的,人们要先利用现有的水晶柱建立若干个结界,然后在某些结界的中心建立祭坛。 例如上右图中,黑色的点表示水晶柱(注意 P 和 O 点不是水晶柱)。祭坛的一个最佳位置为 O 点,可以建立在 3 层结界中,其结界的具体方案见下左图。当然,建立祭坛的最佳位置不一定是唯一,在上右图中,O 点左侧 1 单位的点 P 也可以建立一个在 3 层结界中的祭坛,见下右图。 现在人们想知道: 1. 祭坛最佳选址地点所在的结界层数; 2. 祭坛最佳的选址地点共有多少个。 输入格式
输入的第一行包含两个正整数 n,q,表示水晶柱的个数和问题的种类。保证 q=1 或 2,其意义见输出格式。
接下来 n 行,每行包含两个非负整数 x,y,表示每个水晶柱的坐标。保证相同的坐标不会重复出现。 输出格式
若 q=1,输出一行一个整数,表示祭坛最多可以位于多少个结界的中心;若 q=2,输出一行一个整数,表示结界数最多的方案有多少种。
样例1输入
26 1
0 5 1 1 1 5 1 9 3 5 3 10 4 0 4 1 4 2 4 4 4 6 4 9 4 11 5 0 5 2 5 4 5 8 5 9 5 10 5 11 6 5 7 5 8 5 9 10 10 2 10 5 样例1输出
3
样例2输入
26 2
0 5 1 1 1 5 1 9 3 5 3 10 4 0 4 1 4 2 4 4 4 6 4 9 4 11 5 0 5 2 5 4 5 8 5 9 5 10 5 11 6 5 7 5 8 5 9 10 10 2 10 5 样例2输出
2
样例说明
样例即为题目描述中的例子,两个样例数据相同,分别询问最多的结界数量和达到最多结界数量的方案数。
其中图片的左下角为原点,右和上分别是 x 轴和 y 轴的正方向,一个格子的长度为单位长度。 以图中的 O 点建立祭坛,祭坛最多可以位于 3 个结界的中心。不存在更多结界的方案,因此样例1的答案为 3。 在 O 点左侧 1 单位的点 (4,5) 也可以建立一个在 3 个结界中的祭坛,因此样例2的答案为 2。 评测用例规模与约定
对于所有的数据,保证存在至少一种方案,使得祭坛建造在至少一层结界中,即不存在无论如何祭坛都无法建造在结界中的情况。
数据分为 8 类,各类之间互相没有交集,分别有以下特点: 1. 占数据的 10%,n=200,x,y≤n; 2. 占数据的 10%,n=200,x,y≤109; 3. 占数据的 10%,n=1000,x,y≤n; 4. 占数据的 10%,n=1000,x,y≤109; 5. 占数据的 10%,n=5000,x,y≤n; 6. 占数据的 10%,n=5000,x,y≤109; 7. 占数据的 20%,n=300000,x,y≤n; 8. 占数据的 20%,n=300000,x,y≤109。 此外,每类数据中,q=1 与 q=2 各占恰好一半。 |
80分的做法(引自这里)
主要思路:
先考虑一个比较简单的情况:
给定一条横线上的点(a,b0),(a,b1)...(a,bn),以及一条竖线上的点(a0,b),(a1,b)...(an,b),求两条线能组成的最多结界数。
很容易找出做法:
1)找出两条线的交点(a,b)
2)从交点向外的四个方向(上下左右)上最少的点的数量就是最多结界数。
可以看出上面的想法是正确的。(一种构造方法是,将四个方向上离(a,b)最近的四个点连起来成为一个屏障,第二近的组成一个屏障,第三近的...)
这个可以通过二分查找确定出来。
知道了以上的简单情况,复杂的情况就好说了。。复杂的情况就是很多根竖线和很多根横线相交的问题。直观的想法就是,每根横线和每个竖线都测一下可以做多少结界。然后找出最大的并计数即可。但是这样有一点浪费时间,举个例子,如果我们得到的最大结界数是n,那么任何有少于2n-1的横线是没有必要再检查了(产生n个结界至少要有2n个点)。所以每当得到一个更大的结界数,我们就可以做一次更新,把那些不可能的线段剔除掉,这样可以节约一点时间。
//80 #pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math") #include<vector> #include<algorithm> #include<iostream> using namespace std; #define pb emplace_back const int N=3e5+5; template<typename T> inline void read(T &x){ register bool f=0;register char ch=getchar();x=0; for(;ch<‘0‘||ch>‘9‘;ch=getchar()) if(ch==‘-‘) f=1; for(;ch>=‘0‘&&ch<=‘9‘;ch=getchar()) x=(x<<3)+(x<<1)+ch-‘0‘; if(f) x=-x; } template<typename T,typename...Args> void read(T &x,Args&...args){read(x);read(args...);} int n,Q,cnt=0,ans=0,cur=0; struct node{ int x,y; node(){} node(int x,int y):x(x),y(y){} bool operator <(const node &a)const{ return x!=a.x?x<a.x:y<a.y; } }a[N],b[N]; vector<vector<node> >c(1),d(1); void deal(node (&a)[N],vector<vector<node> > &v){ v[cnt=0].pb(a[0]); for(int i=1;i<n;i++){ if(a[i].x==a[i-1].x){ v[cnt].pb(a[i]); } else{ if(v[cnt].size()==1){ v[cnt][0]=a[i]; } else{ v.pb(vector<node>()); v[++cnt].pb(a[i]); } } } } inline bool comp(const vector<node> &a,const vector<node> &b){ return a.size() > b.size(); } inline int getlr(vector<node> &c,int key){ if(key<=c[0].y) return 0; int l=0,r=c.size(),mid; while(l<r-1){ mid=(l+r)>>1; if(c[mid].y==key) return 0; if(c[mid].y<key) l=mid; else r=mid; } return min(l+1,int(c.size()-l-1)); } int main(){ read(n,Q); for(int i=0,x,y;i<n;i++) read(x,y),a[i]=node(x,y); sort(a,a+n); for(int i=0;i<n;i++) b[i]=node(a[i].y,a[i].x); sort(b,b+n); deal(a,c);deal(b,d); sort(c.begin(),c.end(),comp); sort(d.begin(),d.end(),comp); for(int i=0;i<c.size();i++){ for(int j=0;j<d.size();j++){ int x=c[i][0].x; int y=d[j][0].x; cur=min(getlr(c[i],y),getlr(d[j],x)); if(ans<cur){ ans=cur; cnt=1; while(!c.empty()&&c.back().size()<(ans*2)) c.pop_back(); while(!d.empty()&&d.back().size()<(ans*2)) d.pop_back(); } else if(ans==cur){ cnt++; } } } printf("%d ",Q==1?ans:cnt); return 0; }
以上是关于CCF 201609-5 祭坛的主要内容,如果未能解决你的问题,请参考以下文章