题意:给一个凸包,含有N个点,求删除每个点后再求凸包,凸包上的点的平均值。以p/q的最简形式输出,起初q=N。题目要求凸包不允许有两条相邻边平行。
链接:http://codeforces.com/gym/100492 A题
解法:咋一看没啥思路,可能会想到枚举删除每个点,其左边的点到右边的点再求一次凸包 这样的方法,虽然复杂度依然是O(N)的,但是这样编码起来极其困难,而且容易写挂。多想一想,发现只需求若干次凸包即可,正解如下。先求一次凸包,假设凸包上有偶数个点1..n,接下来,每两个点间接着屏蔽,先屏蔽凸包上1,3,5,… n-1号点,然后求一次凸包,此时表示1,3,5,… n-1号点被删除时候的情况,计算出答案之一,再屏蔽2,4,6,… n号点,再计算一次,除此之外,还要计算删除不在凸包上的点的情况。三次答案之和为最终答案。当凸包上的点为奇数时,需要多加一次计算,但做法类似。注意三或四次计算时的计算方法,不要统计少或多。
小结:此题属于方法好就好写,方法不好就很难写甚至“无法写“的题目,思维难度大,编码容易,多写此类型题有助于思维提高。
//Hello. I‘m Peter.
//#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<iostream>
#include<sstream>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<cctype>
#include<ctime>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();}
while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
return x*f;
}
const double eps = 1e-9, pi = acos(-1.0);
inline int dcmp(double x){
if(fabs(x) < eps) return 0;
else if(x > 0) return 1;
else return -1;
}
struct Point{
double x, y;
int id;
Point(){};
Point(double x1, double y1){
x = x1;
y = y1;
}
};
typedef Point Vector;
Vector operator - (const Vector a, const Vector b){
return Vector(a.x - b.x, a.y - b.y);
}
double operator % (const Vector a, const Vector b){
return a.x * b.y - a.y * b.x;
}
bool cmp1(const Point a, const Point b){
if(dcmp(a.x - b.x) != 0) return a.x < b.x;
else return a.y < b.y;
}
#define N 200010
int notvis[N],kase;
void ConvexHull(Point *p, int n, Point *c, int &m){
m = 0;
for(int i = 0; i < n; i++){
if(notvis[p[i].id] == kase) continue;
while(m > 1 && dcmp((c[m-1] - c[m-2]) % (p[i] - c[m-1])) <= 0) m--;
c[m++] = p[i];
}
int k = m;
for(int i = n - 2; i >= 0; i--){
if(notvis[p[i].id] == kase) continue;
while(m > k && dcmp((c[m-1] - c[m-2]) % (p[i] - c[m-1])) <= 0) m--;
c[m++] = p[i];
}
if(m > 1) m--;
}
Point p[N], c[N], d[N];
int n, m, nd;
ll up, down;
int main(){
freopen("average.in","r",stdin);
freopen("average.out","w",stdout);
n = read();
for(int i = 0; i < n; i++){
int x, y;
x = read(), y = read();
p[i] = Point(x, y);
p[i].id = i;
notvis[i] = 0;
}
sort(p, p + n, cmp1);
kase = 1;
ConvexHull(p, n, c, m);
down = n;
up = 1LL * (n - m) * m;
if(m & 1){
kase ++;
for(int i = 0; i < m - 1; i += 2){
notvis[c[i].id] = kase;
}
ConvexHull(p, n, d, nd);
up += nd - ((m>>1) + 1) + 1LL * (m>>1) * (m - 1);
kase ++;
for(int i = 1; i < m - 1; i += 2){
notvis[c[i].id] = kase;
}
ConvexHull(p, n, d, nd);
up += nd - ((m>>1) + 1) + 1LL * (m>>1) * (m - 1);
kase++;
notvis[c[m-1].id] = kase;
ConvexHull(p, n, d, nd);
up += nd;
}
else{
kase ++;
for(int i = 0; i < m; i += 2){
notvis[c[i].id] = kase;
}
ConvexHull(p, n, d, nd);
up += nd - (m>>1) + 1LL * (m>>1) * (m - 1);
kase ++;
for(int i = 1; i < m; i += 2){
notvis[c[i].id] = kase;
}
ConvexHull(p, n, d, nd);
up += nd - (m>>1) + 1LL * (m>>1) * (m - 1);
}
ll g = __gcd(up, down);
up /= g, down /= g;
cout<<up<<"/"<<down<<endl;
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-23 05:01:27