답안 #17975

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
17975 2016-01-16T11:58:31 Z gs14004 경계 (BOI14_demarcation) C++14
0 / 100
29 ms 2460 KB
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <limits.h>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <algorithm>
#include <string>
#include <functional>
#include <vector>
#include <numeric>
#include <deque>
#include <bitset>
#include <iostream>
using namespace std;
typedef long long lint;
typedef long double llf;
typedef pair<int, int> pi;
const int oo = 1e9;

int n;
vector<pi> a;

lint ccw(pi a, pi b, pi c){
	int dx1 = b.first - a.first;
	int dy1 = b.second - a.second;
	int dx2 = c.first - a.first;
	int dy2 = c.second - a.second;
	return 1ll * dx1 * dy2 - 1ll * dy1 * dx2;
}

void normalize(vector<pi> &v){
	int minx = 1e9, miny = 1e9;
	for(auto &i : v){
		minx = min(minx, i.first);
		miny = min(miny, i.second);
	}
	for(auto &i : v){
		i.first -= minx;
		i.second -= miny;
	}
	rotate(v.begin(), min_element(v.begin(), v.end()), v.end());
}

void reflect(vector<pi> &v){
	for(auto &i : v){
		i.first = -i.first;
	}
	normalize(v);
}

void turn(vector<pi> &v){
	for(auto &i : v){
		i = pi(-i.second, i.first);
	}
	normalize(v);
}

lint get_area(vector<pi> &v){
	lint ret = 0;
	for(int i=2; i<v.size(); i++){
		ret += ccw(v[0], v[i-1], v[i]);
	}
	return ret;
}

bool hapdong(vector<pi> &v1, vector<pi> &v2){
	normalize(v1);
	normalize(v2);
	for(int i=0; i<4; i++){
		turn(v2);
		if(v1 == v2) return 1;
	}
	reflect(v2);
	for(int i=0; i<4; i++){
		turn(v2);
		if(v1 == v2) return 1;
	}
	reverse(v2.begin(), v2.end());
	normalize(v2);
	for(int i=0; i<4; i++){
		turn(v2);
		if(v1 == v2) return 1;
	}
	reflect(v2);
	for(int i=0; i<4; i++){
		turn(v2);
		if(v1 == v2) return 1;
	}
	return 0;
}

void debug(vector<pi> &v){
	printf("%d ", v.size());
	for(auto &i : v) printf("(%d, %d) ", i.first, i.second);
	puts("");
}

bool mid(int s, int x, int e){
	return 1ll * (e-x) * (x-s) >= 0;
}

bool smid(int s, int x, int e){
	return 1ll * (e-x) * (x-s) > 0;
}

void cut_polygon(vector<pi> &in, vector<pi> &out1, vector<pi> &out2, int sx, int ex, int y){
	if(get_area(in) < 0) reverse(in.begin(), in.end());
	int p = min_element(in.begin(), in.end(), [&](const pi &a, const pi &b){
		return a.second < b.second;
	}) - in.begin();
	if(in[p].second >= y){
		out2 = in;
		return;
	}
	int cpos = 0;
	for(int i=0; i<in.size(); i++){
		pi p1 = in[p%in.size()];
		pi p2 = in[(p+1)%in.size()];
		p++;
		if(p1.second != p2.second && smid(p1.second, y, p2.second) && mid(sx, p1.first, ex)){
			if(cpos == 0) out1.push_back(p1);
			else out2.push_back(p2);
			out1.push_back(pi(p1.first, y));
			out2.push_back(pi(p1.first, y));
			cpos ^= 1;
		}
		else if(p1.second == y && p2.second == y && (mid(sx, p1.first, ex) || mid(sx, p2.first, ex))){
			if(sx != -1e9 && ex != 1e9 && smid(sx, p1.first, ex) && smid(sx, p2.first, ex)){
				out1 = in;
				out2.clear();
				return;
			}
			if(cpos == 0) out1.push_back(p1);
			else out2.push_back(p1);
			cpos ^= 1;
		}
		else{
			if(cpos == 0) out1.push_back(p1);
			else out2.push_back(p1);
		}
	}
	// printf("%d %d %d %d\n",sx,ex,sy,ey);
	// debug(out1), debug(out2);
}

int rsx = -1, rsy = -1, rex = -1, rey = -1;

bool non_enclosing(int sx, int ex, int y){
	for(int i=0; i<n; i++){
		pi p1 = a[i];
		pi p2 = a[(i+1)%n];
		if(p1.second != y || p2.second != y) continue;
		if(p1.first > p2.first) swap(p1, p2);
		if(smid(sx, p1.first, ex) && smid(sx, p2.first, ex)) return 0;
	}
	return 1;
}

void save_results(int sx, int ex, int y){
	for(int i=0; i<n; i++){
		pi p1 = a[i];
		pi p2 = a[(i+1)%n];
		if(p1.second != y || p2.second != y) continue;
		if(p1.first > p2.first) swap(p1, p2);
		if(p1.first <= sx) sx = max(sx, p2.first);
		if(p2.first >= ex) ex = min(ex, p1.first);
	}
	rsx = sx;
	rex = ex;
	rsy = y;
	rey = y;
}

struct swp{
	int yc, xc, act;
	bool operator<(const swp &b)const{
		return yc < b.yc;
	}
};

void solve(){
	vector<swp> event;
	set<int> line;
	for(int i=0; i<n; i++){
		pi p1 = a[i];
		pi p2 = a[(i+1)%n];
		if(p1.second == p2.second) continue;
		if(p1.second > p2.second) swap(p1, p2);
		event.push_back({p1.second, p1.first, 1});
		event.push_back({p2.second, p1.first, -1});
	}
	sort(event.begin(), event.end());
	for(int i=0; i<event.size(); ){
		int e = i;
		while(e < event.size() && event[e].yc == event[i].yc){
			if(event[e].act == 1) line.insert(event[e].xc);
			else line.erase(event[e].xc);
			e++;
		}
		if(line.empty()){
			i = e;
			continue;
		}
		auto it1 = line.begin(), it2 = ++line.begin();
		int sy = event[i].yc, ey = event[e].yc;
		while(it2 != line.end()){
			vector<pi> tmp, split1, split2;
			cut_polygon(a, split1, tmp, *it1, *it2, sy);
			tmp.clear();
			cut_polygon(a, tmp, split2, *it1, *it2, ey);
			tmp.clear();
			lint area1 = abs(get_area(split1));
			lint area2 = abs(get_area(split2));
			if(abs(area2 - area1) % (2 * *it2 - 2 * *it1) == 0){
				lint dx = (area2 - area1) / (2 * *it2 - 2 * *it1);
				lint dx2 = ey - sy;
				if(abs(dx) % 2 == dx2 % 2){
					lint q = (dx2 + dx) / 2;
					split1.clear();
					split2.clear();
					if(sy + q >= sy && sy + q <= ey){
						cut_polygon(a, split1, split2, *it1, *it2, sy + q);
						if(non_enclosing(*it1, *it2, sy + q) && hapdong(split1, split2)){
							save_results(*it1, *it2, sy+q);
							return;
						}
					}
				}
			}
			it1++;
			it1++;
			if(it1 == line.end()) break;
			it2++;
			it2++;
		}
		i = e;
	}
}

void point12(){
	int s = 0, e = 1e9;
	while(s != e){
		int m = (s+e)/2;
		vector<pi> v1, v2;
		cut_polygon(a, v1, v2, -oo, oo, m);
		if(abs(get_area(v1)) < abs(get_area(v2))){
			s = m+1;
		}
		else e = m;
	}
	vector<pi> v1, v2;
	cut_polygon(a, v1, v2, -oo, oo, s);
	if(hapdong(v1, v2)){
		vector<int> crd;
		for(int i=0; i<n; i++){
			pi p1 = a[i];
			pi p2 = a[(i+1)%n];
			if(p1.second == s && p2.second != s){
				crd.push_back(p1.first);
			}
			if(p2.second == s && p1.second != s){
				crd.push_back(p1.first);
			}
			if(smid(p1.second, s, p2.second)){
				for(int i=0; i<2; i++) crd.push_back(p1.first);
			}
		}
		sort(crd.begin(), crd.end());
		save_results(crd[1], crd[2], s);
	}
}

int main(){
	scanf("%d",&n);
	a.resize(n);
	for(int i=0; i<n; i++){
		scanf("%d %d",&a[i].first, &a[i].second);
	}
	for(int i=0; i<2; i++){
		if(n > 2000) point12();
		else solve();
		if(i == 1) swap(rsx, rsy), swap(rex, rey);
		if(rsx != -1){
			printf("%d %d %d %d",rsx, rsy, rex, rey);
			return 0;
		}
		for(int i=0; i<n; i++){
			swap(a[i].first, a[i].second);
		}
	}
	puts("NO");
}

Compilation message

demarcation.cpp: In function 'lint get_area(std::vector<std::pair<int, int> >&)':
demarcation.cpp:64:16: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
  for(int i=2; i<v.size(); i++){
                ^
demarcation.cpp: In function 'void debug(std::vector<std::pair<int, int> >&)':
demarcation.cpp:97:24: warning: format '%d' expects argument of type 'int', but argument 2 has type 'std::vector<std::pair<int, int> >::size_type {aka long unsigned int}' [-Wformat=]
  printf("%d ", v.size());
                        ^
demarcation.cpp: In function 'void cut_polygon(std::vector<std::pair<int, int> >&, std::vector<std::pair<int, int> >&, std::vector<std::pair<int, int> >&, int, int, int)':
demarcation.cpp:120:16: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
  for(int i=0; i<in.size(); i++){
                ^
demarcation.cpp: In function 'void solve()':
demarcation.cpp:197:16: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
  for(int i=0; i<event.size(); ){
                ^
demarcation.cpp:199:11: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
   while(e < event.size() && event[e].yc == event[i].yc){
           ^
demarcation.cpp: In function 'int main()':
demarcation.cpp:278:16: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  scanf("%d",&n);
                ^
demarcation.cpp:281:43: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   scanf("%d %d",&a[i].first, &a[i].second);
                                           ^
# 결과 실행 시간 메모리 Grader output
1 Correct 29 ms 2460 KB Output is correct
2 Correct 0 ms 2036 KB Output is correct
3 Correct 0 ms 2036 KB Output is correct
4 Correct 13 ms 2444 KB Output is correct
5 Incorrect 0 ms 2036 KB Output isn't correct
6 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 0 ms 2036 KB Output is correct
2 Correct 0 ms 2036 KB Output is correct
3 Incorrect 0 ms 2036 KB Output isn't correct
4 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 0 ms 2036 KB Output is correct
2 Correct 0 ms 2036 KB Output is correct
3 Incorrect 0 ms 2036 KB Output isn't correct
4 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 29 ms 2460 KB Output is correct
2 Correct 0 ms 2036 KB Output is correct
3 Correct 0 ms 2036 KB Output is correct
4 Correct 9 ms 2444 KB Output is correct
5 Incorrect 0 ms 2036 KB Output isn't correct
6 Halted 0 ms 0 KB -