Submission #377376

# Submission time Handle Problem Language Result Execution time Memory
377376 2021-03-14T06:31:09 Z koioi.org-koosaga 색종이 (kriii3_T) C++17
36 / 109
914 ms 2028 KB
#include <bits/stdc++.h>
using namespace std;
using lint = long long;
using llf = long double;
#define sz(v) ((int)(v).size())
#define all(v) (v).begin(), (v).end()
const int MAXN = 505;
const llf eps = 1e-14L;
const llf pi = acos(-1);

int sgn(llf x){
	if(fabs(x) < eps) return 0;
	return x < 0 ? -1 : 1;
}

llf norm(llf x){
	x = fmod(x, 2 * pi);
	while(x < 0) x += 2 * pi;
	return x;
}


template<class T>
struct Point {
	typedef Point P;
	T x, y;
	explicit Point(T x=0, T y=0) : x(x), y(y) {}
	bool operator<(P p) const { return tie(x,y) < tie(p.x,p.y); }
	bool operator==(P p) const { return sgn(x - p.x) == 0 && sgn(y - p.y) == 0; }
	P operator+(P p) const { return P(x+p.x, y+p.y); }
	P operator-(P p) const { return P(x-p.x, y-p.y); }
	P operator*(T d) const { return P(x*d, y*d); }
	P operator/(T d) const { return P(x/d, y/d); }
	llf dot(P p) const { return x*p.x + y*p.y; }
	T cross(P p) const { return x*p.y - y*p.x; }
	T cross(P a, P b) const { return (a-*this).cross(b-*this); }
	T dist2() const { return x*x + y*y; }
	llf dist() const { return sqrt((llf)dist2()); }
	// angle to x-axis in interval [-pi, pi]
	llf angle() const { return atan2(y, x); }
	P unit() const { return *this/dist(); } // makes dist()=1
	P perp() const { return P(-y, x); } // rotates +90 degrees
	P normal() const { return perp().unit(); }
	// returns point rotated 'a' radians ccw around the origin
	P rotate(llf a) const {
		return P(x*cos(a)-y*sin(a),x*sin(a)+y*cos(a)); }
};

using punk = Point<llf>;

llf fix(llf x){
	if(sgn(x) == 0) return 0;
	return x;
}

llf ccw(punk A, punk B, punk C){
	return A.cross(B, C);
}

llf dot(punk A, punk B, punk C){
	return (B - A).dot(C - A);
}

struct triangle {
	punk p[3];
	int idx;
	void input(){
		for(int j = 0; j < 3; j++){
			cin >> p[j].x >> p[j].y;
		}
		if(p[0].cross(p[1], p[2]) < 0) swap(p[1], p[2]);
	}
	bool in(punk x){
		for(int j = 0; j < 3; j++){
			if(ccw(p[j], p[(j+1)%3], x) < -eps) return 0;
		}
		return 1;
	}
};

struct circle{
	punk C; llf r;
	int idx;
	bool in(punk x){
		llf dist = (x - C).dist2();
		if(sgn(dist - r * r) > 0) return 0;
		return 1;
	}
	bool operator!=(const circle &c){
		return sgn((c.C - C).dist2()) != 0 || sgn(r - c.r) != 0;
	}
};

template<class P>
int segmentIntersection(const P& s1, const P& e1,
		const P& s2, const P& e2, P& r1, P& r2) {
	if (e1==s1) {
		if (e2==s2) {
			if (e1==e2) { r1 = e1; return 1; } //all equal
			else return 0; //different point segments
		} else return segmentIntersection(s2,e2,s1,e1,r1,r2);//swap
	}
	//segment directions and separation
	P v1 = e1-s1, v2 = e2-s2, d = s2-s1;
	auto a = v1.cross(v2), a1 = v1.cross(d), a2 = v2.cross(d);
	if (a == 0) { //if parallel
		auto b1=s1.dot(v1), c1=e1.dot(v1),
			 b2=s2.dot(v1), c2=e2.dot(v1);
		if (a1 || a2 || max(b1,min(b2,c2))>min(c1,max(b2,c2)))
			return 0;
		r1 = min(b2,c2)<b1 ? s1 : (b2<c2 ? s2 : e2);
		r2 = max(b2,c2)>c1 ? e1 : (b2>c2 ? s2 : e2);
		return 2-(r1==r2);
	}
	if (a < 0) { a = -a; a1 = -a1; a2 = -a2; }
	if (0<a1 || a<-a1 || 0<a2 || a<-a2)
		return 0;
	r1 = s1-v1*a2/a;
	return 1;
}

template<class P>
bool circleIntersection(P a, P b, llf r1, llf r2,
		pair<P, P>* out) {
	P delta = b - a;
	if(sgn(delta.dist2()) == 0) return false;
	llf r = r1 + r2, d2 = delta.dist2();
	llf p = (d2 + (r1 - r2) * (r1 + r2)) / (2.0 * d2);
	llf h2 = r1*r1 - p*p*d2;
	if (d2 > r*r + eps || h2 < -eps) return false;
	P mid = a + delta*p, per = delta.perp() * sqrt(fix(h2 / d2));
	*out = {mid + per, mid - per};
	return true;
}

bool segmentCircle(punk A, punk B, punk C, llf r, punk &X, punk &Y){
	llf dis = fabs(ccw(A, B, C)) / (B - A).dist();
	if(sgn(dis - r) > 0) return 0;
	punk M = A + (B - A) * (dot(A, B, C) / (B - A).dist2());
	punk D = (B - A).unit() * sqrt(fix(r * r - dis * dis));
	X = M - D;
	Y = M + D;
	return 1;
}

llf dx[MAXN][MAXN];
llf ret;

bool sameDirection(punk A, punk B, punk C, punk D){
	return sgn((B - A).dot(D - C)) > 0;
}

void solve_circle(circle x, vector<triangle> t, vector<circle> c){
	vector<llf> witness = {0, 2 * pi};
	auto ratio = [&](punk C){
		C = C - x.C;
		llf ans = atan2l(C.y, C.x);
		while(ans < 0) ans += 2 * pi;
		return ans;
	};
	for(auto &i : t){
		if(x.idx == i.idx) continue;
		for(int j = 0; j < 3; j++){
			punk C = i.p[j];
			punk D = i.p[(j+1)%3];
			punk X, Y;
			if(segmentCircle(C, D, x.C, x.r, X, Y)){
				witness.push_back(ratio(X));
				witness.push_back(ratio(Y));
			}
		}
	}
	for(auto &i : c){
		if(x.idx == i.idx) continue;
		pair<punk, punk> P;
		if(circleIntersection(i.C, x.C, i.r, x.r, &P)){
			witness.push_back(ratio(P.first));
			witness.push_back(ratio(P.second));
		}
	}
	sort(all(witness));
	for(int i = 1; i < sz(witness); i++){
		llf m = (witness[i - 1] + witness[i]) / 2;
		punk M = x.C + punk(x.r, 0).rotate(m);
		int min_idx = -1;
		int max_idx = sz(t) + sz(c);
		for(auto &j : t){
			if(j.idx == x.idx) continue;
			if(j.in(M)){
				if(j.idx < x.idx) min_idx = max(min_idx, j.idx);
				else max_idx = min(max_idx, j.idx);
			}
		}
		for(auto &j : c){
			if(j.idx == x.idx) continue;
			if(j.in(M)){
				if(j.idx < x.idx){
					if(j != x) min_idx = max(min_idx, j.idx);
				}
				else max_idx = min(max_idx, j.idx);
			}
		}
		llf theta = witness[i] - witness[i - 1];
		punk p1 = punk(1, 0).rotate(witness[i - 1]);
		punk p2 = punk(1, 0).rotate(witness[i]);
		llf result = x.r * x.r * theta + x.r * x.C.cross(p2 - p1);
		for(int i = x.idx; i < max_idx; i++){
			dx[min_idx + 1][i] += result;
			dx[x.idx + 1][i] -= result;
		}
	}
}

void solve_line(triangle x, vector<triangle> t, vector<circle> c){
	for(int i = 0; i < 3; i++){
		punk A = x.p[i];
		punk B = x.p[(i+1)%3];
		vector<llf> witness = {0, 1};
		auto ratio = [&](punk C){
			if(sgn(A.x - B.x) == 0) return (C.y - A.y) / (B.y - A.y);
			return (C.x - A.x) / (B.x - A.x);
		};
		for(auto &i : t){
			if(x.idx == i.idx) continue;
			for(int j = 0; j < 3; j++){
				punk C = i.p[j];
				punk D = i.p[(j+1)%3];
				if(sgn(ccw(A, B, C)) == 0 && sgn(ccw(A, B, D)) == 0){
					witness.push_back(ratio(C));
					witness.push_back(ratio(D));
				}
				else{
					punk X, Y;
					int val = segmentIntersection(A, B, C, D, X, Y);
					assert(val != 2);
					if(val){
						llf r = ratio(X);
						witness.push_back(r);
					}
				}
			}
		}
		for(auto &i : c){
			punk P, Q;
			if(segmentCircle(A, B, i.C, i.r, P, Q)){
				llf r1 = ratio(P), r2 = ratio(Q);
				if(r1 > r2) swap(r1, r2);
				witness.push_back(r1);
				witness.push_back(r2);
			}
		}
		sort(all(witness));
		for(int i = 1; i < sz(witness); i++){	
			if(fabs(witness[i] - witness[i-1]) < eps) continue;
			if(witness[i - 1] < -eps || witness[i] > 1 + eps) continue;
			llf m = (witness[i - 1] + witness[i]) / 2;
			auto P = A + (B - A) * witness[i - 1];
			auto Q = A + (B - A) * witness[i];
			auto M = A + (B - A) * m;
			int min_idx = -1;
			int max_idx = sz(t) + sz(c);
			for(auto &j : t){
				if(j.idx == x.idx) continue;
				if(j.in(M)){
					bool over = false;
					punk X, Y;
					if(segmentIntersection(P, Q, j.p[0], j.p[1], X, Y) == 2 &&
							sameDirection(A, B, j.p[0], j.p[1])) over = true;
					if(segmentIntersection(P, Q, j.p[1], j.p[2], X, Y) == 2 &&
							sameDirection(A, B, j.p[1], j.p[2])) over = true;
					if(segmentIntersection(P, Q, j.p[2], j.p[0], X, Y) == 2 &&
							sameDirection(A, B, j.p[2], j.p[0])) over = true;
					if(over){
						if(j.idx < x.idx) min_idx = max(min_idx, j.idx);
					}
					else{
						if(j.idx < x.idx) min_idx = max(min_idx, j.idx);
						else max_idx = min(max_idx, j.idx);
					}
				}
			}
			for(auto &j : c){
				if(j.idx == x.idx) continue;
				if(j.in(M)){
					if(j.idx < x.idx) min_idx = max(min_idx, j.idx);
					else max_idx = min(max_idx, j.idx);
				}
			}
			llf result = A.cross(B) * (witness[i] - witness[i - 1]);
			for(int i = x.idx; i < max_idx; i++){
				dx[min_idx + 1][i] += result;
				dx[x.idx + 1][i] -= result;
			}
		}
	}
}

int main(){
	int n;
	cin >> n;
	vector<triangle> vt;
	vector<circle> vc;
	for(int i = 0; i < n; i++){
		int t;
		scanf("%d",&t);
		if(t == 1){
			triangle c; c.input();
			vt.push_back(c);
			vt.back().idx = i;
		} else {
			int x, y, r; 
			scanf("%d %d %d",&x,&y,&r);
			vc.push_back({punk(x, y), llf(r)});
			vc.back().idx = i;
		}
	}
	for(auto &i : vt) solve_line(i, vt, vc);
	for(auto &i : vc) solve_circle(i, vt, vc);
	for(int i = 0; i < n; i++){
		for(int j = 0; j <= i; j++){
			printf("%.20Lf ", 0.5 * -dx[j+1][i]);
		}
		puts("");
	}
}

Compilation message

paper.cpp: In function 'int main()':
paper.cpp:305:8: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  305 |   scanf("%d",&t);
      |   ~~~~~^~~~~~~~~
paper.cpp:312:9: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  312 |    scanf("%d %d %d",&x,&y,&r);
      |    ~~~~~^~~~~~~~~~~~~~~~~~~~~
# Verdict Execution time Memory Grader output
1 Correct 173 ms 1812 KB Output is correct
2 Correct 157 ms 1772 KB Output is correct
3 Correct 141 ms 1772 KB Output is correct
4 Correct 131 ms 1772 KB Output is correct
5 Correct 127 ms 1772 KB Output is correct
6 Correct 144 ms 1772 KB Output is correct
7 Correct 140 ms 1764 KB Output is correct
8 Correct 128 ms 1772 KB Output is correct
9 Correct 108 ms 1772 KB Output is correct
10 Correct 116 ms 1772 KB Output is correct
11 Correct 44 ms 1772 KB Output is correct
12 Correct 51 ms 1772 KB Output is correct
13 Correct 96 ms 1900 KB Output is correct
14 Correct 87 ms 1772 KB Output is correct
15 Correct 95 ms 1772 KB Output is correct
16 Correct 68 ms 1772 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 446 ms 1772 KB Output is correct
2 Correct 487 ms 1900 KB Output is correct
3 Correct 428 ms 1848 KB Output is correct
4 Correct 452 ms 1900 KB Output is correct
5 Correct 455 ms 2028 KB Output is correct
6 Incorrect 914 ms 1900 KB Output isn't correct
7 Halted 0 ms 0 KB -