蒟蒻求助
查看原帖
蒟蒻求助
27765
河城白露楼主2023/9/25 18:57

70pts,wa#4#7#8

只wa在最长点对,旋转卡壳的板子题过了

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <iostream>
#include <string>
#include <set>
#include <map>
#include <vector>
#include <queue>
#define ll long long
#define db double
using namespace std;
const db EPS = 1e-10;
const db INF = 1e40;
const ll N = 1e5 + 100;
// 浮点数加法处理
db add(db va, db vb) {
	if (abs(va + vb) < EPS * (abs(va) + abs(vb))) {
		return 0;
	}
	return va + vb;
}
// 平方
db sq(db val) {
	return val * val;
}
// 点、向量结构体
struct P {
	db x,y;
	P() {};
	P(db x, db y) : x(x) , y(y) {
	}
  // 四则运算
	P operator + (P const &p) const {
		return P(add(x,p.x),add(y,p.y));
	}
	P operator - (P const &p) const {
		return P(add(x,-p.x),add(y,-p.y));
	}
	P operator * (db const &d) const {
		return P(x * d, y * d);
	}
	P operator / (db const &d) const {
		return P(x / d, y / d);
	}
	bool operator < (P const &p) const {
		if (x == p.x) {
			return y < p.y;
		}
		return x < p.x;
	}
  // 点积
	db dot(P p) {
		return add(x * p.x, y * p.y);
	}
  // 叉积
	db det(P p) {
		return add(x * p.y, -y * p.x);
	}
  // 模长平方
	db modl() {
		return sq(x) + sq(y);
	}
};
// 两点之间的距离
db disPnt(P px, P py) {
	return sqrt(sq(py.x - px.x) + sq(py.y - px.y));
}
// 递归求平面最小点对(确认没有问题)
db closeDis(ll l, ll r, P * arr) {
	if (r - l < 1) {
		return INF;
	}
	ll mid = (l + r) >> 1;
	db val = arr[mid].x;
	db dis = min(closeDis(l,mid,arr),closeDis(mid + 1,r,arr));
	sort(arr + l,arr + r + 1,[] (P const &px, P const &py) {
		return px.y < py.y;
	});
	vector<P> b;
	for (ll i = l;i <= r;i++) {
		if (abs(arr[i].x - val) > dis) {
			continue;
		}
		for (ll j = b.size() - 1;j >= 0;j--) {
			if (arr[i].y - b[j].y > dis) {
				break;
			}
			dis = min(dis,disPnt(arr[i],b[j]));
		}
		b.push_back(arr[i]);
	}
	return dis;
}
// 多边形结构体,本质是点集
struct Poly {
	vector<P> pSet;
	Poly() {};
	Poly(vector<P> const &pSet) : pSet(pSet) {
	}
  // 生成凸包,Andrew算法
	void conGene() {
      // 取出点集长度
		ll len = pSet.size();
      // 把最下最左的点放在第一个
		for (ll i = 1;i < len;i++) {
			if (pSet[i].y - pSet[0].y < -EPS) {
				swap(pSet[0],pSet[i]);
			} else {
				if ((abs(pSet[i].y - pSet[0].y) < EPS) && (pSet[i].x - pSet[0].x < -EPS)) {
					swap(pSet[0],pSet[i]);
				}
			}
		}
      // 极角排序
		sort(pSet.begin() + 1,pSet.end(),[&](const P &px, const P &py) {
			P vx = px - pSet[0];
			P vy = py - pSet[0];
          // 极角相同按照距离第一个点的距离从小到大排序
			if (abs(vx.det(vy)) < EPS) {
				return (vy.modl() - vx.modl() < EPS);
			} else {
				return (vx.det(vy) > EPS);
			}
		});
      // 构建栈
		vector<P> stk;
      // 算法核心
		for (ll i = 0;i < len;i++) {
			if (stk.empty()) {
				stk.push_back(pSet[i]);
			} else {
				ll top = stk.size() - 1;
				while(top > 0) {
					P vx = stk[top] - stk[top - 1];
					P vy = pSet[i] - stk[top - 1];
					if (vx.det(vy) < -EPS) {
						stk.pop_back();
						top--;
					} else {
						break;
					}
				}
				stk.push_back(pSet[i]);
			}
		}
		pSet.clear();
      // 将生成后的凸多边形赋给点集
		swap(pSet, stk);
	}
  // 求凸包直径,旋转卡壳
	db diaCon() {
		ll len = pSet.size();
		db res = 0.0;
      // 活动指针
		ll pt = 2 % len;
		for (ll i = 0;i < len;i++) {
          // 该边的长度与res比较
			res = max(res,disPnt(pSet[i],pSet[(i + 1) % len]));
          // 构建边向量,方便求面积
			P vec = pSet[(i + 1) % len] - pSet[i];
          // 活动指针的下一个指针
			ll nxt = (pt + 1) % len;
          // 如果nxt点与边构成的三角形面积大于pt点与边构成的三角形面积,则指针++
			while(fabs(vec.det(pSet[nxt] - pSet[i])) - fabs(vec.det(pSet[pt] - pSet[i])) > 0) {
				pt = nxt;
				nxt = (nxt + 1) % len;
			}
          // 计算点对长度
			res = max(res,max(disPnt(pSet[i],pSet[pt]),disPnt(pSet[(i + 1) % len],pSet[pt])));
		}
		return res;
	}
};

ll tt,n;
// 使用该数组求平面最小点对
P pnt[N];
void solve() {
	scanf("%lld",&n);
  // 使用该数组求平面最大点对
	vector<P> pnts;
	for (ll i = 1;i <= n;i++) {
		db x,y;
		scanf("%lf%lf",&x,&y);
		pnt[i] = P(x,y);
		pnts.push_back(pnt[i]);
	}
  // 求最小点对前先按照x排序
	sort(pnt + 1,pnt + n + 1);
	db ansmn = closeDis(1,n,pnt);
  // 构建多边形
	Poly poly = Poly(pnts);
  // 生成凸包
	poly.conGene();
  // 求凸包直径
	db ansmx = poly.diaCon();
	printf("%.12lf %.12lf",ansmn,ansmx);
}
int main() {
	tt = 1;
	while(tt) {
		solve();
		tt--;
	}
	return 0;
}

2023/9/25 18:57
加载中...