답안 #430203

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
430203 2021-06-16T12:04:17 Z koioi.org-koosaga Power plants (CPSPC17_power) C++17
0 / 100
3 ms 2764 KB
#include <bits/stdc++.h>
using namespace std;
using lint = long long;
using pi = pair<int, int>;
#define sz(v) ((int)(v).size())
#define all(v) (v).begin(), (v).end()

const int MAXN = 100005;
typedef long long ll;

namespace DT{
	using ll = long long;

	bool ge(const ll& a, const ll& b) { return a >= b; }
	bool le(const ll& a, const ll& b) { return a <= b; }
	bool eq(const ll& a, const ll& b) { return a == b; }
	bool gt(const ll& a, const ll& b) { return a > b; }
	bool lt(const ll& a, const ll& b) { return a < b; }
	int sgn(const ll& a) { return a >= 0 ? a ? 1 : 0 : -1; }

	struct pt {
		int x, y;
		pt() { }
		pt(ll _x, ll _y) : x(_x), y(_y) { }
		bool operator<(const pt &p)const{
			return make_pair(x, y) < make_pair(p.x, p.y);
		}
		bool operator>(const pt &p)const{
			return make_pair(x, y) > make_pair(p.x, p.y);
		}

		pt operator-(const pt& p) const {
			return pt(x - p.x, y - p.y);
		}
		ll cross(const pt& p) const {
			return 1ll * x * p.y - 1ll * y * p.x;
		}
		ll cross(const pt& a, const pt& b) const {
			return (a - *this).cross(b - *this);
		}
		ll dot(const pt& p) const {
			return 1ll * x * p.x + 1ll * y * p.y;
		}
		ll dot(const pt& a, const pt& b) const {
			return (a - *this).dot(b - *this);
		}
		ll sqrLength() const {
			return this->dot(*this);
		}
		bool operator==(const pt& p) const {
			return eq(x, p.x) && eq(y, p.y);
		}
	};

	const pt inf_pt = pt(2e9, 2e9);

	struct QuadEdge {
		pt origin;
		QuadEdge* rot = nullptr;
		QuadEdge* onext = nullptr;
		bool used = false;
		QuadEdge* rev() const {
			return rot->rot;
		}
		QuadEdge* lnext() const {
			return rot->rev()->onext->rot;
		}
		QuadEdge* oprev() const {
			return rot->onext->rot;
		}
		pt dest() const {
			return rev()->origin;
		}
	};

	QuadEdge* make_edge(pt from, pt to) {
		QuadEdge* e1 = new QuadEdge;
		QuadEdge* e2 = new QuadEdge;
		QuadEdge* e3 = new QuadEdge;
		QuadEdge* e4 = new QuadEdge;
		e1->origin = from;
		e2->origin = to;
		e3->origin = e4->origin = inf_pt;
		e1->rot = e3;
		e2->rot = e4;
		e3->rot = e2;
		e4->rot = e1;
		e1->onext = e1;
		e2->onext = e2;
		e3->onext = e4;
		e4->onext = e3;
		return e1;
	}

	void splice(QuadEdge* a, QuadEdge* b) {
		swap(a->onext->rot->onext, b->onext->rot->onext);
		swap(a->onext, b->onext);
	}

	void delete_edge(QuadEdge* e) {
		splice(e, e->oprev());
		splice(e->rev(), e->rev()->oprev());
		delete e->rev()->rot;
		delete e->rev();
		delete e->rot;
		delete e;
	}

	QuadEdge* connect(QuadEdge* a, QuadEdge* b) {
		QuadEdge* e = make_edge(a->dest(), b->origin);
		splice(e, a->lnext());
		splice(e->rev(), b);
		return e;
	}

	bool left_of(pt p, QuadEdge* e) {
		return gt(p.cross(e->origin, e->dest()), 0);
	}

	bool right_of(pt p, QuadEdge* e) {
		return lt(p.cross(e->origin, e->dest()), 0);
	}

	template <class T>
		T det3(T a1, T a2, T a3, T b1, T b2, T b3, T c1, T c2, T c3) {
			return a1 * (b2 * c3 - c2 * b3) - a2 * (b1 * c3 - c1 * b3) +
				a3 * (b1 * c2 - c1 * b2);
		}

	bool in_circle(pt a, pt b, pt c, pt d) {
		long double det = -det3<long double>(b.x, b.y, b.sqrLength(), c.x, c.y,
				c.sqrLength(), d.x, d.y, d.sqrLength());
		det += det3<long double>(a.x, a.y, a.sqrLength(), c.x, c.y, c.sqrLength(), d.x,
				d.y, d.sqrLength());
		det -= det3<long double>(a.x, a.y, a.sqrLength(), b.x, b.y, b.sqrLength(), d.x,
				d.y, d.sqrLength());
		det += det3<long double>(a.x, a.y, a.sqrLength(), b.x, b.y, b.sqrLength(), c.x,
				c.y, c.sqrLength());
		if(fabs(det) > 1e18) return det > 0;
		else{

			ll det = -det3<ll>(b.x, b.y, b.sqrLength(), c.x, c.y,
					c.sqrLength(), d.x, d.y, d.sqrLength());
			det += det3<ll>(a.x, a.y, a.sqrLength(), c.x, c.y, c.sqrLength(), d.x,
					d.y, d.sqrLength());
			det -= det3<ll>(a.x, a.y, a.sqrLength(), b.x, b.y, b.sqrLength(), d.x,
					d.y, d.sqrLength());
			det += det3<ll>(a.x, a.y, a.sqrLength(), b.x, b.y, b.sqrLength(), c.x,
					c.y, c.sqrLength());
			return (det > 0);
		}
	}

	pair<QuadEdge*, QuadEdge*> build_tr(int l, int r, vector<pt>& p) {
		if (r - l + 1 == 2) {
			QuadEdge* res = make_edge(p[l], p[r]);
			return make_pair(res, res->rev());
		}
		if (r - l + 1 == 3) {
			QuadEdge *a = make_edge(p[l], p[l + 1]), *b = make_edge(p[l + 1], p[r]);
			splice(a->rev(), b);
			int sg = sgn(p[l].cross(p[l + 1], p[r]));
			if (sg == 0)
				return make_pair(a, b->rev());
			QuadEdge* c = connect(b, a);
			if (sg == 1)
				return make_pair(a, b->rev());
			else
				return make_pair(c->rev(), c);
		}
		int mid = (l + r) / 2;
		QuadEdge *ldo, *ldi, *rdo, *rdi;
		tie(ldo, ldi) = build_tr(l, mid, p);
		tie(rdi, rdo) = build_tr(mid + 1, r, p);
		while (true) {
			if (left_of(rdi->origin, ldi)) {
				ldi = ldi->lnext();
				continue;
			}
			if (right_of(ldi->origin, rdi)) {
				rdi = rdi->rev()->onext;
				continue;
			}
			break;
		}
		QuadEdge* basel = connect(rdi->rev(), ldi);
		auto valid = [&basel](QuadEdge* e) { return right_of(e->dest(), basel); };
		if (ldi->origin == ldo->origin)
			ldo = basel->rev();
		if (rdi->origin == rdo->origin)
			rdo = basel;
		while (true) {
			QuadEdge* lcand = basel->rev()->onext;
			if (valid(lcand)) {
				while (in_circle(basel->dest(), basel->origin, lcand->dest(),
							lcand->onext->dest())) {
					QuadEdge* t = lcand->onext;
					delete_edge(lcand);
					lcand = t;
				}
			}
			QuadEdge* rcand = basel->oprev();
			if (valid(rcand)) {
				while (in_circle(basel->dest(), basel->origin, rcand->dest(),
							rcand->oprev()->dest())) {
					QuadEdge* t = rcand->oprev();
					delete_edge(rcand);
					rcand = t;
				}
			}
			if (!valid(lcand) && !valid(rcand))
				break;
			if (!valid(lcand) ||
					(valid(rcand) && in_circle(lcand->dest(), lcand->origin,
											   rcand->origin, rcand->dest())))
				basel = connect(rcand, basel->rev());
			else
				basel = connect(basel->rev(), lcand->rev());
		}
		return make_pair(ldo, rdo);
	}

	vector<tuple<pt, pt, pt>> delaunay(vector<pt> p) {
		sort(p.begin(), p.end(), [](const pt& a, const pt& b) {
				return lt(a.x, b.x) || (eq(a.x, b.x) && lt(a.y, b.y));
				});
		auto res = build_tr(0, (int)p.size() - 1, p);
		QuadEdge* e = res.first;
		vector<QuadEdge*> edges = {e};
		while (lt(e->onext->dest().cross(e->dest(), e->origin), 0))
			e = e->onext;
		auto add = [&p, &e, &edges]() {
			QuadEdge* curr = e;
			do {
				curr->used = true;
				p.push_back(curr->origin);
				edges.push_back(curr->rev());
				curr = curr->lnext();
			} while (curr != e);
		};
		add();
		p.clear();
		int kek = 0;
		while (kek < (int)edges.size()) {
			if (!(e = edges[kek++])->used)
				add();
		}
		vector<tuple<pt, pt, pt>> ans;
		for (int i = 0; i < (int)p.size(); i += 3) {
			ans.push_back(make_tuple(p[i], p[i + 1], p[i + 2]));
		}
		return ans;
	}

		bool in_triangle(pt a, pt b, pt c, pt d){
		if((b - a).cross(c - a) < 0) swap(b, c);
		if((b - a).cross(d - a) < 0) return 0;
		if((c - b).cross(d - b) < 0) return 0;
		if((a - c).cross(d - c) < 0) return 0;
		return 1;
	}


}

struct edge{
	int s, e; lint x;
	bool operator<(const edge &e)const{
		return x < e.x;
	}
};

struct disj{
	int pa[MAXN];
	void init(int n){
		iota(pa, pa + n, 0);
	}
	int find(int x){
		return pa[x] = (pa[x] == x ? x : find(pa[x]));
	}
	bool uni(int p, int q){
		p = find(p); q = find(q);
		if(p == q) return 0;
		pa[q] = p; return 1;
	}
}disj;
namespace GGD{

	int n;
	pi a[100005];

	bool cmp(pi a, pi b){return a.second < b.second;}
	lint dist(pi x, pi y){return 1ll*(y.second - x.second) * (y.second - x.second) + 1ll*(y.first - x.first) * (y.first - x.first);}

	lint closest(int s, int e){
		if(s == e-2){
			return min(min(dist(a[s],a[s+1]),dist(a[s+1],a[s+2])),dist(a[s],a[s+2]));
		}
		if(s == e-1){
			return dist(a[s],a[e]);
		}
		int m = (s+e)/2;
		lint res = min(closest(s,m),closest(m+1,e));

		vector<pi> strip;
		for (int i=s; i<=e; i++) {
			if(abs(a[i].first - a[m].first) < res){
				strip.push_back(a[i]);
			}
		}
		sort(strip.begin(),strip.end(),cmp);
		for (int i=0; i<strip.size(); i++) {
			for (int j=i+1; j<strip.size() &&
				1ll*	(strip[j].second - strip[i].second) * (strip[j].second - strip[i].second) < res; j++){
				res = min(res,dist(strip[j],strip[i]));
			}
		}
		return res;
	}

	lint getdist(vector<DT::pt> v){
		n = sz(v);
		for (int i=0; i<n; i++) {
			a[i] = pi(v[i].x, v[i].y);
		}
		sort(a,a+n);
		return closest(0, n - 1);
	}

};

vector<int> gph[MAXN];
int col[MAXN];

lint dist(DT::pt a, DT::pt b){
	lint dx = b.x - a.x;
	lint dy = b.y - a.y;
	return dx*dx+dy*dy;
}



void dfs(int x, int c, int p = -1){
	col[x] = c;
	for(auto &i : gph[x]){
		if(i != p) dfs(i, 3-c, x);
	}
}

int main(){
	int n;
	scanf("%d",&n);
	vector<DT::pt> a(n);
	map<DT::pt, int> mp;
	int cnt = 0;
	for(auto &i : a){
		scanf("%d %d",&i.x,&i.y);
		mp[i] = cnt++;
	}
	vector<edge> v;
	auto dt = DT::delaunay(a);
	for(int i=0; i<sz(dt); i++){
		auto [x, y, z] = dt[i];
		auto edges = {make_pair(x, y), make_pair(x, z), make_pair(y, z)};
		for(auto &[x, y] : edges){
			v.push_back({mp[x], mp[y], dist(x,y)});
		}
	}
	sort(all(v));
	disj.init(n);
	for(int i=0; i<sz(v); i++){
		if(disj.uni(v[i].s, v[i].e)){
			gph[v[i].s].push_back(v[i].e);
			gph[v[i].e].push_back(v[i].s);
		}
	}
	dfs(0, 1);
	{
	vector<DT::pt> v[2];
	for(int i = 0; i < n; i++){
		v[col[i] - 1].push_back(a[i]);
	}
	printf("%lld\n", max(GGD::getdist(v[0]), GGD::getdist(v[1])));
	for(int i = 0; i < 2; i++){
		printf("%d\n", sz(v[i]));
		for(int j = 0; j < n; j++){
			if(col[j] == i + 1) printf("%d ", j + 1);
		}
		puts("");
	}
	}
}

Compilation message

Main.cpp: In function 'lint GGD::closest(int, int)':
Main.cpp:312:18: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  312 |   for (int i=0; i<strip.size(); i++) {
      |                 ~^~~~~~~~~~~~~
Main.cpp:313:21: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  313 |    for (int j=i+1; j<strip.size() &&
      |                    ~^~~~~~~~~~~~~
Main.cpp: In function 'int main()':
Main.cpp:352:7: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  352 |  scanf("%d",&n);
      |  ~~~~~^~~~~~~~~
Main.cpp:357:8: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  357 |   scanf("%d %d",&i.x,&i.y);
      |   ~~~~~^~~~~~~~~~~~~~~~~~~
# 결과 실행 시간 메모리 Grader output
1 Incorrect 3 ms 2764 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 3 ms 2764 KB Output isn't correct
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Incorrect 3 ms 2764 KB Output isn't correct
2 Halted 0 ms 0 KB -