CF97B:Superset——题解
http://codeforces.com/problemset/problem/97/B
题目大意:给n个点,添加一些点,使得任意两个点:
1.在同一条线上
2.以它们为顶点构成的矩形上有其他点。
输出一组可行解。
——————————————————
我发现我根本不会做英语题……看了半天题面后就去找题解了。
http://blog.csdn.net/wust_zjx/article/details/44900093
这是其他人的题解,但我总觉得这个人说的不明不白的(自行理解半个小时才明白的我深有感触)
首先题告诉我们随意一组解都可以,这给我们很大的自由空间,直接开始想暴力。
……但是我们不可以把点填满(题中有最大点数限制)
我们通过二分平面,对于mid点,每个在l-r中的其他的点与该点所在直线的投影就是我们需要添加的点(显然)。
同时为了防止我们添加重复的点我们需要用set维护一下。
Q1:为什么我们只需要在区间中的点的投影?
A1:我们知道在大区间内我们已经把所有的点投影到了mid,那么我们画图后发现我们对于右边的区间和左边的区间中的点一定满足上面的两种条件,故不需要加点。
Q2:为什么可行?
A2:(数都是约数)第一次我们添加了n个点,第二次我们添加了n/2*2个点,第三次我们添加了n/4*4个点……我们添加logn次,我们总共添加了nlogn个点大约1.2*10^5,总共也就大约1.3*10^5个点,一定超不了。
#include<cmath> #include<cstdio> #include<cctype> #include<cstring> #include<set> #include<algorithm> #define x first #define y second using namespace std; typedef pair<int,int>ii; inline int read(){ int X=0,w=0; char ch=0; while(!isdigit(ch)) {w|=ch=='-';ch=getchar();} while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X; } ii p[10001]; set<ii>s; void solve(int l,int r){ if(l>=r)return; int mid=(l+r)>>1; for(int i=l;i<=r;i++){ s.insert(ii(p[mid].x,p[i].y)); } solve(l,mid); solve(mid+1,r); return; } int main(){ int n=read(); for(int i=1;i<=n;i++){ p[i].x=read(); p[i].y=read(); s.insert(p[i]); } sort(p+1,p+n+1); solve(1,n); printf("%d\n",(int)s.size()); for(set<ii>::iterator i=s.begin();i!=s.end();i++){ printf("%d %d\n",i->x,i->y); } return 0; }