-
Notifications
You must be signed in to change notification settings - Fork 224
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
fcdbce0
commit c71b58c
Showing
2 changed files
with
302 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,285 @@ | ||
#include <algorithm> | ||
#include <cassert> | ||
#include <cstdio> | ||
#include <cstdlib> | ||
#include <cctype> | ||
#include <cmath> | ||
#include <iostream> | ||
#include <sstream> | ||
#include <string> | ||
#include <utility> | ||
#include <vector> | ||
#include <cassert> | ||
#include <ctime> | ||
#include <queue> | ||
using namespace std; | ||
#define VAR(a,b) __typeof(b) a=(b) | ||
#define REP(i,n) for(int _n=n, i=0;i<_n;++i) | ||
#define FOR(i,a,b) for(int i=(a),_b=(b);i<=_b;++i) | ||
#define FORD(i,a,b) for(int i=(a),_b=(b);i>=_b;--i) | ||
#define FOREACH(it,c) for(VAR(it,(c).begin());it!=(c).end();++it) | ||
#define ALL(c) (c).begin(),(c).end() | ||
#define DEBUG(x) cerr << #x << " = " << x << "\n"; | ||
template<class T> | ||
ostream& operator<<(ostream&o, const vector<T>&v) { | ||
o<<'{'; | ||
FOREACH(it,v) o<<*it<<','; | ||
return o<<'}'; | ||
} | ||
typedef long long LL; | ||
const int INF = 1000000000; const LL INFLL = LL(INF) * LL(INF); | ||
typedef vector<int> VI; typedef vector<string> VS; typedef vector<VI> VVI; | ||
template<class T> inline int size(const T&c) { return c.size(); } | ||
int rint() { int x; if(scanf("%d",&x)!=1) return -1; return x; } | ||
string rstring() { char buf[1000]; scanf("%s",buf); return buf; } | ||
//}}} | ||
typedef long double ld; | ||
class INPUT { | ||
static const int BUFSIZE = 1<<16; | ||
static char buffer[]; | ||
char *bufpos; | ||
char *bufend; | ||
void grabBuffer(); | ||
public: | ||
INPUT() { grabBuffer(); } | ||
bool eof() { return bufend==buffer; } | ||
char nextChar() { return *bufpos; } | ||
inline char readChar(); | ||
inline void skipWS(); | ||
inline unsigned readUnsigned(); | ||
inline int readInt(); | ||
inline ld readLD(); | ||
}; | ||
|
||
char INPUT::buffer[INPUT::BUFSIZE]; | ||
|
||
void INPUT::grabBuffer() { | ||
bufpos = buffer; | ||
bufend = buffer + read(0, buffer, BUFSIZE); | ||
} | ||
|
||
char INPUT::readChar() { | ||
char res = *bufpos++; | ||
if(bufpos==bufend) grabBuffer(); | ||
return res; | ||
} | ||
|
||
inline bool myisspace(char c) { return c<=' '; } | ||
|
||
void INPUT::skipWS() { | ||
while(!eof() && myisspace(nextChar())) readChar(); | ||
} | ||
|
||
unsigned INPUT::readUnsigned() { | ||
skipWS(); | ||
unsigned res = 0; | ||
while(!eof() && isdigit(nextChar())) { | ||
res = 10u * res + (readChar()-'0'); | ||
} | ||
return res; | ||
} | ||
|
||
int INPUT::readInt() { | ||
skipWS(); | ||
bool neg = false; | ||
if(!eof() && nextChar()=='-') { neg=true; readChar(); } | ||
int res = static_cast<int>(readUnsigned()); | ||
if(neg) res = -res; | ||
return res; | ||
} | ||
|
||
ld INPUT::readLD() { | ||
skipWS(); | ||
bool neg=false; | ||
if(nextChar()=='-') { neg=true; readChar(); } | ||
ld res = 0; | ||
while(!eof() && isdigit(nextChar())) { | ||
res = 10 * res + (readChar()-'0'); | ||
} | ||
if(nextChar()=='.') { | ||
readChar(); | ||
ld p = 0.1; | ||
while(!eof() && isdigit(nextChar())) { | ||
res += p * (readChar()-'0'); | ||
p *= 0.1; | ||
} | ||
} | ||
if(neg) res = -res; | ||
return res; | ||
} | ||
|
||
INPUT input; | ||
|
||
|
||
const ld EPS = 1e-7; | ||
const ld EPS2 = EPS*EPS; | ||
|
||
ld PI = 2*acosl(0.0); | ||
|
||
struct Point { | ||
ld x,y; | ||
Point() {} | ||
Point(ld x,ld y):x(x),y(y) {} | ||
}; | ||
|
||
inline bool operator<(const Point &a, const Point &b) { | ||
return a.x < b.x || a.x == b.x && a.y < b.y; | ||
} | ||
|
||
inline Point operator+(const Point &A,const Point&B) { return Point(A.x+B.x,A.y+B.y); } | ||
inline Point operator-(const Point &A,const Point&B) { return Point(A.x-B.x,A.y-B.y); } | ||
inline Point operator*(ld c, const Point &A) { return Point(c*A.x,c*A.y); } | ||
inline ld operator%(const Point&A,const Point&B) { return A.x*B.y-A.y*B.x; } | ||
inline ld operator*(const Point&A,const Point&B) { return A.x*B.x+A.y*B.y; } | ||
inline ld len2(const Point&A) { return A*A; } | ||
inline ld len(const Point&A) { return sqrtl(len2(A)); } | ||
inline Point turn90(const Point &A) { | ||
return Point(-A.y, A.x); | ||
} | ||
|
||
void printPoint(const Point &a) { | ||
printf("(%.6Lf, %.6Lf)\n", a.x, a.y); | ||
} | ||
|
||
vector<Point> points; | ||
|
||
void readPoints() { | ||
int n = input.readInt(); | ||
points.clear(); points.reserve(n); | ||
ld minx = 1e100, maxx = -1e100, miny=1e100, maxy=-1e100; | ||
REP(i,n) { | ||
ld x = input.readLD(); | ||
ld y = input.readLD(); | ||
points.push_back(Point(x,y)); | ||
minx = min(minx, x); | ||
maxx = max(maxx, x); | ||
miny = min(miny, y); | ||
maxy = max(maxy, y); | ||
} | ||
if(maxx-minx>=2 || maxy-miny >= 2) throw 0; | ||
Point center((minx+maxx)/2, (miny+maxy)/2); | ||
FOREACH(it, points) *it = *it - center; | ||
} | ||
|
||
void calcHull() { | ||
sort(points.begin(), points.end()); | ||
vector<Point> hull; | ||
hull.push_back(points[0]); | ||
int st = 0; | ||
FOR(i,1,size(points)-1) { | ||
Point p = points[i]; | ||
while(size(hull)-st >= 2 && | ||
(hull[size(hull)-1] - hull[size(hull)-2]) % | ||
(p - hull[size(hull)-2]) <= EPS2) { | ||
hull.pop_back(); | ||
} | ||
if(len2(p-hull[size(hull)-1]) > EPS2) | ||
hull.push_back(p); | ||
} | ||
st = size(hull)-1; | ||
FORD(i,size(points)-1,0) { | ||
Point p = points[i]; | ||
while(size(hull)-st >= 2 && | ||
(hull[size(hull)-1] - hull[size(hull)-2]) % | ||
(p - hull[size(hull)-2]) <= EPS2) { | ||
hull.pop_back(); | ||
} | ||
if(len2(p-hull[size(hull)-1]) > EPS2) | ||
hull.push_back(p); | ||
} | ||
hull.pop_back(); | ||
points.swap(hull); | ||
} | ||
|
||
vector<int> next,prev,todo; | ||
vector<int> todoStack; | ||
|
||
Point circleCenter(const Point &a, const Point &b) { | ||
Point c = 0.5 * (a+b); | ||
Point ac = c-a; | ||
ld x2 = len2(ac); | ||
ld y2 = 1-x2; | ||
if(y2<=0) throw 0; | ||
Point res = c + sqrtl(y2/x2) * turn90(ac); | ||
return res; | ||
} | ||
|
||
void process(int x) { | ||
int a = prev[x]; | ||
int b = next[x]; | ||
if(a==x || b==x || a==b) return; | ||
Point cen = circleCenter(points[a], points[b]); | ||
if(len2(cen-points[x]) <= 1+EPS) { | ||
next[a] = b; prev[b] = a; | ||
next[x] = -1; prev[x] = -1; | ||
if(!todo[a]) { todo[a]=1; todoStack.push_back(a); } | ||
if(!todo[b]) { todo[b]=1; todoStack.push_back(b); } | ||
} | ||
} | ||
|
||
vector<Point> answerPoly; | ||
|
||
void buildAnswerPoly() { | ||
answerPoly.clear(); | ||
int st = 0; | ||
while(next[st]==-1) ++st; | ||
int a = st; | ||
do { | ||
int b = next[a]; | ||
Point p = points[a]; | ||
Point q = points[b]; | ||
Point c = circleCenter(p,q); | ||
answerPoly.push_back(c); | ||
a = b; | ||
} while(a!=st); | ||
} | ||
|
||
ld calcArea() { | ||
int n = size(answerPoly); | ||
ld res = 0; | ||
REP(i,n) { | ||
Point p = answerPoly[i]; | ||
Point q = answerPoly[(i+1)%n]; | ||
res += 0.5 * (p%q); | ||
ld d = len(p-q); | ||
ld alpha = asinl(0.5*d); | ||
res += alpha; | ||
res -= 0.5 * sinl(2*alpha); | ||
} | ||
return res; | ||
} | ||
|
||
ld calc() { | ||
int n = size(points); | ||
if(n<2) return PI; | ||
next.resize(n); | ||
prev.resize(n); | ||
todo.assign(n,1); | ||
todoStack.resize(n); | ||
REP(i,n) { | ||
next[i] = (i+1)%n; | ||
prev[i] = (i+n-1)%n; | ||
todoStack[i] = i; | ||
} | ||
while(!todoStack.empty()) { | ||
int x = todoStack.back(); | ||
todoStack.pop_back(); | ||
todo[x] = 0; | ||
process(x); | ||
} | ||
buildAnswerPoly(); | ||
return calcArea(); | ||
} | ||
|
||
int main() { | ||
int ntc = input.readInt(); | ||
REP(tc,ntc) { | ||
ld res; | ||
try { | ||
readPoints(); | ||
calcHull(); | ||
res = calc(); | ||
} catch(int) { res = 0; } | ||
printf("%.6Lf\n", res); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
Overlapping discs https://www.codechef.com/problems/M5 | ||
Description- | ||
You are given n discs on plane, of the same radius (r=1). Output the area of the part of the plane which is covered by each disc. | ||
|
||
Constraints- | ||
First, 1<=t<=10, the number of tests. Each testcase is of the following form: 1<=n<=100000, then n pairs of floating point coordinates follow: -1000<=xi,yi<=1000, representing the location of the i-th disc. | ||
|
||
Example- | ||
Input: | ||
1 | ||
2 | ||
0 0 | ||
0 1 | ||
|
||
Output: | ||
1.228370 | ||
|