1. 程式人生 > >CF97B:Superset——題解

CF97B:Superset——題解

1.2 body art spa 開始 ash sort iterator 維護

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; }

CF97B:Superset——題解