Submission #377300

# Submission time Handle Problem Language Result Execution time Memory
377300 2021-03-13T18:33:47 Z koioi.org-koosaga 색종이 (kriii3_T) C++17
36 / 109
955 ms 2008 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;
				bool bad = 0;
				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) bad = 1;
					}
					else bad = 1;
				}
				if(bad){
					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;
			}
		}
	}
}



void solve(){
	int n;
	if(scanf("%d",&n) != 1) exit(0);
	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("");
	}
}

int main(){
	while(1){
		solve();
	}
}

Compilation message

paper.cpp: In function 'void solve()':
paper.cpp:309:8: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  309 |   scanf("%d",&t);
      |   ~~~~~^~~~~~~~~
paper.cpp:316:9: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  316 |    scanf("%d %d %d",&x,&y,&r);
      |    ~~~~~^~~~~~~~~~~~~~~~~~~~~
# Verdict Execution time Memory Grader output
1 Correct 171 ms 1772 KB Output is correct
2 Correct 166 ms 1772 KB Output is correct
3 Correct 157 ms 1900 KB Output is correct
4 Correct 136 ms 1772 KB Output is correct
5 Correct 139 ms 1776 KB Output is correct
6 Correct 148 ms 1772 KB Output is correct
7 Correct 139 ms 1772 KB Output is correct
8 Correct 150 ms 1772 KB Output is correct
9 Correct 106 ms 1772 KB Output is correct
10 Correct 118 ms 1772 KB Output is correct
11 Correct 46 ms 1772 KB Output is correct
12 Correct 51 ms 1772 KB Output is correct
13 Correct 103 ms 1772 KB Output is correct
14 Correct 94 ms 2008 KB Output is correct
15 Correct 112 ms 1772 KB Output is correct
16 Correct 64 ms 1772 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 481 ms 1984 KB Output is correct
2 Correct 483 ms 1900 KB Output is correct
3 Correct 463 ms 1972 KB Output is correct
4 Correct 458 ms 1900 KB Output is correct
5 Correct 463 ms 1860 KB Output is correct
6 Incorrect 955 ms 1992 KB Output isn't correct
7 Halted 0 ms 0 KB -