BZOJ2178 圆的面积并

计算几何题。别人都用simpson搞。然后我决定不水一发,用hwd神犇在wc上讲的关键点法做。

 

然后就搞到了12点半。发现坑数次。还专门用js写了个画圆的。当然我现在知道怎么画圆了。过两天去把oj7的统计图改一改。

 

思路是把所有圆的左右端点和所有圆的两两交的x提出来,unique一发(不然会tle显然的)。这样两个x之间的部分的圆弧是不会有交的。那么就可以视为一堆弓形和梯形了。然后扫描一下中位线的有效长度算梯形。每次新进入一个连通区域和出来的时候加相应弓形的面积。

 

需要注意按y排序的时候是按弓形与竖线的交点的y,而不是梯形的y,否则会有非常神奇的精度误差。另外算弓形面积必需要用反三角函数(至少我没研究出怎么不用)。如果用acos的话会暴精度暴得很惨。要用atan2来提高精度。

 

然后这样写连样例都会tle。仔细感受一下发现好像如果有一堆同心圆的话都会tle。然后考虑去掉包含的圆之后似乎就快了。然后就交了,然后居然跑过了。

 

然后来欣赏一下我的时间巨大,空间巨大,长度巨大。挤在一堆simpson里显得特别郁闷的代码。

 

#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>

using namespace std;

const double eps = 1e-8;
const double pi = acos(-1);

inline int sgn(double x) {
	return (x > eps) - (x < -eps);
}
inline double sqr(double x) {
	return x * x;
}

typedef struct geo_obj {
	double x, y;
	geo_obj() {}
	geo_obj(double xo, double yo) {
		x = xo, y = yo;
	}
	inline void read() {
		scanf("%lf%lf", &x, &y);
	}
	inline geo_obj vertical() {
		return geo_obj(-y, x);
	}
	inline double len() {
		return sqrt(sqr(x) + sqr(y));
	}
} point, vect;
inline geo_obj operator +(const geo_obj& a, const geo_obj& b) {
	return geo_obj(a. x + b. x, a. y + b. y);
}
inline geo_obj operator -(const geo_obj& a, const geo_obj& b) {
	return geo_obj(a. x - b. x, a. y - b. y);
}
inline geo_obj operator *(const geo_obj& a, const double& b) {
	return geo_obj(a. x * b, a. y * b);
}
inline double operator *(const geo_obj& a, const geo_obj& b) {
	return a. x * b. y - a. y * b. x;
}
inline double operator &(const geo_obj& a, const geo_obj& b) {
	return a. x * b. x + a. y * b. y;
}
inline double sqDist(const geo_obj& a, const geo_obj& b) {
	return sqr(a. x - b. x) + sqr(a. y - b. y);
}

struct circle {
	point o;
	double r, sr;
	inline void read() {
		o. read();
		scanf("%lf", &r);
		sr = sqr(r);
	}
};

inline double helenSqr(double a, double b, double c) {
	double p((a + b + c) / 2.0);
	return sqrt(p * (p - a) * (p - b) * (p - c));
}

struct ypr {
	double y, s, yv;
	int v;
};
inline bool operator <(const ypr& a, const ypr& b) {
	return (a. yv < b. yv) || (a. yv == b. yv && a. v > b. v);
}

const int maxn = 1009;
const int maxx = 1002009;

int n, totx;
double x[maxx], ans;
circle a[maxn];
ypr y[maxn << 1];

double arcSqr(circle c, point a, point b) {
	vect x(a - c. o), y(b - c. o);
	double sqt(fabs(x * y));
	double d(sqrt(sqDist(a, b)));
	double tht(atan2(d / 2, sqt / d) * 2);
	//double tht(acos((x & y) / c. sr));
	sqt /= 2;
	return tht * c. sr / 2 - sqt;
}

int main() {
#ifndef ONLINE_JUDGE
	freopen("in.txt", "r", stdin);
#endif

	scanf("%d", &n);
	totx = 0;
	for (int i = 0; i < n; ++ i) { 
		a[i]. read();
		bool thr(0);
		for (int j = 0; j < i && !thr; ++ j)
			if (sqDist(a[i]. o, a[j]. o) <= sqr(a[i]. r - a[j]. r)) {
				if (a[i]. r > a[j]. r)
					swap(a[i], a[j]);
				thr = 1;
			}
		if (thr) {
			-- i;
			-- n;
		}
	}
	for (int i = 0; i < n; ++ i) {
		x[totx ++] = a[i]. o. x - a[i]. r;
		x[totx ++] = a[i]. o. x + a[i]. r;
	}
	for (int i = 1; i < n; ++ i)
		for (int j = 0; j < i; ++ j) {
			double sd(sqDist(a[i]. o, a[j]. o));
			if (sd <= sqr(a[i]. r + a[j]. r) && sd >= sqr(a[i]. r - a[j]. r)) {
				double d(sqrt(sd));
				double s(helenSqr(a[i]. r, a[j]. r, d));
				double h(s * 2 / d);
				double l(sqrt(a[i]. sr - sqr(h)));
				if (sqr(a[j]. r) > sd + sqr(a[i]. r))
					l = -l;
				point p(a[i]. o + (a[j]. o - a[i]. o) * (l / d));
				vect v((a[j]. o - a[i]. o). vertical());
				v = v * (h / v. len());
				x[totx ++] = p. x + v. x;
				x[totx ++] = p. x - v. x;
			}
		}
	sort(x, x + totx);
	totx = unique(x, x + totx) - x;
	ans = 0;
	for (int i = 0; i < totx - 1; ++ i) {
		double xl(x[i]), xr(x[i + 1]);
		int cy(0);
		for (int j = 0; j < n; ++ j) 
			if (a[j]. o. x - a[j]. r < xr && a[j]. o. x + a[j]. r > xl) {
				double yl(sqrt(a[j]. sr - sqr(a[j]. o. x - xl)));
				double yv(sqrt(a[j]. sr - sqr(a[j]. o. x - (xl + xr) / 2.0)));
				double yr(sqrt(a[j]. sr - sqr(a[j]. o. x - xr)));
				double ar(arcSqr(a[j], point(xl, a[j]. o. y - yl), point(xr, a[j]. o. y - yr)));
				double ym((yl + yr) / 2);
				y[cy]. y = a[j]. o. y - ym;
				y[cy]. yv = a[j]. o. y - yv;
				y[cy]. v = 1;
				y[cy]. s = ar;
				++ cy;
				y[cy]. y = a[j]. o. y + ym;
				y[cy]. yv = a[j]. o. y + yv;
				y[cy]. v = -1;
				y[cy]. s = ar;
				++ cy;
			}
		double ml(0);
		sort(y, y + cy);
		for (int j = 0, cnt = 0; j < cy - 1; ++ j) {
			if ((y[j]. v == 1 && !cnt) || (y[j]. v == -1 && cnt == 1))
				ans += y[j]. s;
			cnt += y[j]. v;
			if (cnt)
				ml += y[j + 1]. y - y[j]. y;
		}
		ans += y[cy - 1]. s;
		ans += ml * (xr - xl);
	}
	printf("%.3lf\n", ans);
}

BZOJ1822 [JSOI2010]Frozen Nova 冷冻波

简单的算几+网络流么。然后花了将近两天。最近总和算几过不去啊。

 

判断线段和圆是否有交还是比较简单的。反正不要让我用解析。先找下垂线,然后找下垂足,然后点乘一下搞定。然后错得不知道怎么死的。搞了很久。

 

然后二分网络流水水水水水水水水。

 

感觉mac好卡啊,gdb巨卡,bash也非常卡。难道我又没有搞对打开方式?

 

#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>

using namespace std;

inline long double sqr(long double x) {
	return x * x;
}

typedef struct geo_obj {
	double x, y;
	geo_obj() {}
	geo_obj(double x0, double y0) {
		x = x0, y = y0;
	}
	inline void read() {
		scanf("%lf%lf", &x, &y);
	}
	inline geo_obj rev() {
		return geo_obj(-y, x);
	}
	inline double len() {
		return sqrt(sqr(x) + sqr(y));
	}
	inline double sqLen() {
		return sqr(x) + sqr(y);
	}
} point, vect;
inline geo_obj operator +(const geo_obj& a, const geo_obj& b) {
	return geo_obj(a. x + b. x, a. y + b. y);
}
inline geo_obj operator -(const geo_obj& a, const geo_obj& b) {
	return geo_obj(a. x - b. x, a. y - b. y);
}
inline geo_obj operator *(const geo_obj& a, const double& b) {
	return geo_obj(a. x * b, a. y * b);
}
inline double operator *(const geo_obj& a, const geo_obj& b) {
	return a. x * b. y - a. y * b. x;
}
inline double operator &(const geo_obj& a, const geo_obj& b) {
	return a. x * b. x + a. y * b. y;
}

struct line {
	point p;
	vect v;
	line(point a, point b) {
		p = a;
		v = b - a;
	}
};
struct circle {
	point o;
	double r;
	void read() {
		o. read();
		scanf("%lf", &r);
	}
};

inline point lineCross(const line& a, const line& b) {
	vect w(b. p - a. p);
	double rat((w * a. v) / (a. v * b. v));
	return b. p + b. v * rat;
}

bool segInCircle(point a, point b, circle c) {
	line l(a, b);
	vect u(l. v. rev());
	line r(c. o, c. o + u);
	point p(lineCross(l, r));
	double x = (p - c. o). sqLen();
	double sr(sqr(c. r));
	if (x >= sr)
		return 0;
	if (((a - p) & (b - p)) <= 0)
		return 1;
	if ((a - c. o). sqLen() <= sr)
		return 1;
	if ((b - c. o). sqLen() <= sr)
		return 1;
	return 0;
}

struct edge {
	int t, c;
	edge *next, *rv;
};

struct wiz {
	point p;
	int r, t;
	void read() {
		p. read();
		scanf("%d%d", &r, &t);
	}
};

const int maxn = 409;
const int maxe = 80409;
const int inf = 0x3f3f3f3f;

int n, m, c, t, ea[maxe], eb[maxe], ou[maxn];
int d[maxn], st, te;
wiz w[maxn];
circle tree[maxn];
point spi[maxn];
edge elst[maxe], *ep, *head[maxn << 1];

inline edge* newEdge(int u, int v, int c) {
	ep-> t = v;
	ep-> c = c;
	ep-> next = head[u];
	head[u] = ep;
	return ep ++;
}
inline void addEdge(int u, int v, int c) {
	edge *a = newEdge(u, v, c);
	edge *b = newEdge(v, u, 0);
	a-> rv = b;
	b-> rv = a;
}

bool bfsBuild() {
	static int q[maxn];
	int hd(0), tl(1);
	memset(d, 0, sizeof(d));
	d[q[0] = st] = 1;
	while (hd < tl && !d[te]) {
		int p(q[hd ++]);
		for (edge* e = head[p]; e; e = e-> next)
			if (e-> c && !d[e-> t]) {
				d[e-> t] = d[p] + 1;
				q[tl ++] = e-> t;
			}
	}
	return d[te];
}
int dfsFind(int p, int c) {
	if (p == te)
		return c;
	int s(0);
	edge* e;
	for (e = head[p]; e && c; e = e-> next)
		if (e-> c && d[e-> t] == d[p] + 1) {
			int x(dfsFind(e-> t, min(e-> c, c)));
			s += x;
			c -= x;
			e-> c -= x;
			e-> rv-> c += x;
		}
	if (!e)
		d[p] = -1;
	return s;
}

int binSearch() {
	int l(0), r(5000000);
	st = n + m;
	te = st + 1;
	while (l < r) {
		int mid((l + r) >> 1);
		ep = elst;
		memset(head, 0, sizeof(head));
		for (int i = 0; i < t; ++ i)
			addEdge(ea[i], eb[i] + n, 1);
		for (int i = 0; i < n; ++ i)
			addEdge(st, i, (mid + w[i]. t) / w[i]. t);
		for (int i = 0; i < m; ++ i)
			addEdge(i + n, te, 1);
		int s(0);
		while (bfsBuild())
			s += dfsFind(st, inf);
		if (s == m)
			r = mid;
		else
			l = mid + 1;
	}
	return l;
}

int main() {
#ifndef ONLINE_JUDGE
	freopen("in.txt", "r", stdin);
#endif

	scanf("%d%d%d", &n, &m, &c);
	for (int i = 0; i < n; ++ i)
		w[i]. read();
	for (int i = 0; i < m; ++ i)
		spi[i]. read();
	for (int i = 0; i < c; ++ i)
		tree[i]. read();
	memset(ou, 0, sizeof(ou));
	t = 0;
	for (int i = 0; i < n; ++ i)
		for (int j = 0; j < m; ++ j) {
			bool f(1);
			double ds(sqr(w[i]. p. x - spi[j]. x) + sqr(w[i]. p. y - spi[j]. y));
			if (ds > sqr(w[i]. r))
				f = 0;
			for (int k = 0; k < c && f; ++ k)
				if (segInCircle(w[i]. p, spi[j], tree[k]))
					f = 0;
			if (f) {
				ea[t] = i;
				eb[t] = j;
				++ t;
				ou[j] = 1;
			}
		}
	bool hs(1);
	for (int i = 0; i < m && hs; ++ i)
		if (!ou[i])
			hs = 0;
	if (!hs || !n)
		puts("-1");
	else
		printf("%d\n", binSearch());
}

BZOJ1845 [Cqoi2005] 三角形面积并

比较基础的算几。当是hwd在wc的时候讲的东西拿来练练吧。(都过去多久了)

 

算几的板比较长。然后记得还有道半平面交精度题至今没过!?什么效率。

 

这题的思路比较简单。找出所有的关键x,分段。每段内都是一堆边不相交的梯形,那么答案=∑(▵x*∑中位线并的长度)。总时间复杂度到了O(n3)。不过n才100显然可过。至于n等于1000的题暂时不会啊。我太弱了。

 

然后这题也有神奇的精度误差,答案要-1e-7才能过。

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const double eps = 1e-7;
inline int sgn(double x) {
	return (x > eps) - (x < -eps);
}
inline double sqr(double x) {
	return x * x;
}

typedef struct geo_obj {
	double x, y;
	inline geo_obj() {}
	inline geo_obj(double x0, double y0) {
		x = x0, y = y0;
	}
	inline void read() {
		scanf("%lf%lf", &x, &y);
	}
} point, vect;
inline geo_obj operator +(const geo_obj& a, const geo_obj& b) {
	return geo_obj(a. x + b. x, a. y + b. y);
}
inline geo_obj operator -(const geo_obj& a, const geo_obj& b) {
	return geo_obj(a. x - b. x, a. y - b. y);
}
inline geo_obj operator *(const geo_obj& a, const double& b) {
	return geo_obj(a. x * b, a. y * b);
}
inline double operator *(const geo_obj& a, const geo_obj& b) {
	return a. x * b. y - a. y * b. x;
}
inline double operator &(const geo_obj& a, const geo_obj& b) {
	return a. x * b. x + a. y * b. y;
}
inline bool operator <(const geo_obj& a, const geo_obj& b) {
	return (a. x < b. x) || (a. x == b. x && a. y < b. y);
}

struct line {
	point p;
	vect v;
	inline line() {}
	inline line(const point& a, point& b) {
		p = a, v = b - a;
	}
};
struct triangle {
	point a[3];
	inline triangle() {}
	inline void read() {
		for (int i = 0; i < 3; ++ i)
			a[i]. read();
		if (sgn((a[1] - a[0]) * (a[2] - a[0])) < 0)
			swap(a[1], a[2]);
	}
};

typedef pair <double, int> ypr;

const int maxn = 109;
const int maxp = 90009;
const int ara[3] = {0, 1, 2}, arb[3] = {1, 2, 0};

int n, t, c;
triangle a[maxn];
double x[maxp], ans(0);
ypr y[maxp];

point lineCross(line a, line b) {
	vect w(b. p - a. p);
	double rat((w * a. v) / (a. v * b. v));
	return b. p + b. v * rat;
}

void addX(point a, point b, point c, point d) {
	if (!sgn((b - a) * (d - c)))
		return;
	point e(lineCross(line(a, b), line(c, d)));
	if (((a - e) & (b - e)) > 0 || ((c - e) & (d - e)) > 0)
		return;
	x[t ++] = e. x;
}

int main() {
#ifndef ONLINE_JUDGE
	freopen("in.txt", "r", stdin);
#endif

	scanf("%d", &n);
	for (int i = 0; i < n; ++ i)
		a[i]. read();
	t = 0;
	for (int i = 0; i < n; ++ i) {
		for (int j = 0; j < 3; ++ j)
			x[t ++] = a[i]. a[j]. x;
		for (int j = 0; j < i; ++ j)
			for (int k = 0; k < 3; ++ k)
				for (int l = 0; l < 3; ++ l)
					addX(a[i]. a[ara[k]], a[i]. a[arb[k]], a[j]. a[ara[l]], a[j]. a[arb[l]]);
	}
	sort(x, x + t);
	t = unique(x, x + t) - x;
	for (int i = 0; i < t - 1; ++ i) {
		double xm((x[i] + x[i + 1]) / 2.0);
		c = 0;
		for (int j = 0; j < n; ++ j)
			for (int k = 0; k < 3; ++ k) {
				point u(a[j]. a[ara[k]]), v(a[j]. a[arb[k]]);
				if ((xm - u. x) * (xm - v. x) < 0) {
					point w(u + (v - u) * ((xm - u. x) / (v. x - u. x)));
					y[c ++] = ypr(w. y, (u. x < v. x) ? 1 : -1);
				}
			}
		sort(y, y + c);
		int cnt(0);
		double len(0);
		for (int i = 0; i < c - 1; ++ i) {
			cnt += y[i]. second;
			if (cnt)
				len += (y[i + 1]. first - y[i]. first);
		}
		ans += len * (x[i + 1] - x[i]);
	}
	printf("%.2lf\n", ans - eps);
}

BZOJ2642 Pku3968 Jungle Outpost

看mhy写了好几天了啊。然后研究了一下,居然过得比他早。

 

首先敌人一定可以炸连续的一段。然后就是要看炸掉任意连续一段之后还有没有剩下的公共部分,既半平面交。

 

然后我yy出了一个半平面交的做法。找出一条基准直线,按方向顺时针方向排序。然后按照正常半平面交的方法根据栈顶两个元素和当前直线的位置关系判断是否需要退栈。然后当找到一条与基准直线的角度大于等于π的直线(直线是有向的,也可以说是成负角)且它把栈里退到只剩基准直线一条的时候,这些半平面没有交。否则这些半平面有交。

 

至于证明嘛,我也不会(挠头),毕竟是感受出来的。然后感觉这次代码写得比较漂亮,开心。

 

#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>

using namespace std;

inline double sqr(double x) {
	return x * x;
}

struct point {
	double x, y;
	inline point() {}
	inline point(double x0, double y0) {
		x = x0, y = y0;
	}
	inline void read() {
		scanf("%lf%lf", &x, &y);
	}
};
struct vect {
	double x, y;
	inline vect() {}
	inline vect(double x0, double y0) {
		x = x0, y = y0;
	}
	inline vect(point a, point b) {
		x = b. x - a. x, y = b. y - a. y;
	}
	inline vect vertical() {
		return vect(y, - x);
	}
	inline double length() {
		return sqrt(sqr(x) + sqr(y));
	}
};
struct line {
	point a;
	vect d;
	inline line() {}
	inline line(point u, point v) {
		a = u;
		d = vect(u, v);
	}
};

const double eps = 1e-8;

inline point operator +(const point& a, const vect& b) {
	return point(a. x + b. x, a. y + b. y);
}
inline double operator *(const vect& a, const vect& b) {
	return a. x * b. y - a. y * b. x;
}
inline vect operator *(const vect& a, double r) {
	return vect(a. x * r, a. y * r);
}
inline int sgn(double x) {
	return (fabs(x) < eps) ? 0 : ((x > 0) ? 1 : -1);
}

const int maxn = 50009;

int n, t, li[maxn], tst;
point a[maxn], b[maxn];
line l[maxn];

inline bool outSide(line l, point p) {
	return sgn(vect(l. a, p) * l. d) <= 0;
}

point getCross(line l1, line l2) {
	point a(l1. a), b(l1. a + l1. d);
	point c(l2. a), d(l2. a + l2. d);
	if (!sgn(vect(d, c) * vect(d, b))) {
		d = l2. a + l2. d * 2.0;
		b = l1. a + l1. d * 2.0;
	}
	if (!sgn(vect(d, a) * vect(d, c)))
		a = l1. a + l1. d * 3.0;
	double sa(vect(d, a) * vect(d, c));
	double sb(vect(d, c) * vect(d, b));
	double rat(sa / (sa + sb));
	return point(a + vect(a, b) * rat);
}

bool check(int t) {
	for (int i = 0; i < n; ++ i)
		l[i] = line(a[i], a[(i + t + 1) % n]);
	tst = 2;
	li[1] = 0;
	b[2] = getCross(l[0], l[1]);
	li[2] = 1;
	for (int i = 2; i < n; ++ i) {
		while (tst > 1 && outSide(l[i], b[tst]))
			-- tst;
		if (tst == 1 && sgn(l[i]. d * l[0]. d) <= 0)
			return 0;
		li[++ tst] = i;
		b[tst] = getCross(l[li[tst - 1]], l[i]);
	}
	return tst > 2;
}

int main() {
#ifndef ONLINE_JUDGE
	freopen("in.txt", "r", stdin);
#endif

	scanf("%d", &n);
	for (int i = 0; i <	n; ++ i)
		a[i]. read();
	int l(1), r(n - 2);
	while (l < r) {
		int mid((l + r) >> 1);
		if (check(mid))
			l = mid + 1;
		else
			r = mid;
	}
	printf("%d\n", l);
}

顺便把写的画图的js粘上来好了。以后说不定还有用。

JS not supported

BZOJ1502 [NOI2005]月下柠檬树

今天几乎讲了一天的算几。或者说能听的只有算几。然后就去做了一道基础题。

 

刚开始的时候比较naive,把相交的情况想简单了,打算直接上数学,然后悲剧地发现还有其它的不好算交点的情况,于是就去写simpson了。

 

simpson就是一个估计用的,s = (4 * f(mid) + f(l) + f(r))*(r-l)/6。至于为啥是对的就不知道了。反正比较能用。然后每次直接去扫一遍所有能交的地方,取max就行了,比挨个算交点方便许多。

 

然后第一次写,代码也比较乱。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>

using namespace std;

const int maxn = 509;
const double pi = asin(1) * 2;
const double eps = 1e-6;

#define x1 _x1_
#define x2 _x2_
#define y1 _y1_
#define y2 _y2_

int n;
double tht, x[maxn], h[maxn], r[maxn];
double crd[maxn];
double x1[maxn], x2[maxn], y1[maxn], y2[maxn];
bool c[maxn];

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

inline double sqr(double x) {
	return x * x;
}

void calc() {
	for (int i = 0; i < n; ++ i) {
		int u(i), v(i + 1);
		if (sgn(x[u] - r[u] - x[v] + r[v]) <= 0 && sgn(x[u] + r[u] - x[v] - r[v]) >= 0) {
			c[i] = 0;
		}
		else {
			double ctht((r[u] - r[v]) / (x[v] - x[u])), stht(sqrt(1 - sqr(ctht)));
			x1[i] = x[u] + r[u] * ctht; 
			y1[i] = r[u] * stht;
			x2[i] = x[v] + r[v] * ctht;
			y2[i] = r[v] * stht;
			c[i] = 1;
		}
	}
}

double f(double x0) {
	double y(0);
	for (int i = 0; i <= n; ++ i)
		if (x0 >= x[i] - r[i] && x0 <= x[i] + r[i])
			y = max(y, sqrt(sqr(r[i]) -  sqr(x0 - x[i])));
	for (int i = 0; i < n; ++ i)
		if (c[i] && sgn(x0 - x1[i]) >= 0 && sgn(x0 - x2[i]) <= 0)
			y = max(y, (y1[i] * (x2[i] - x0) + y2[i] * (x0 - x1[i])) / (x2[i] - x1[i]));
	return y;
}

inline double integ(double l, double r) {
	return (f(l) + f(r) + f((l + r) / 2) * 4) * (r - l) / 6;
}

double simpson(double l0, double r0) {
	double mid((l0 + r0) / 2.0);
	double a(integ(l0, r0));
	double b(integ(l0, mid));
	double c(integ(mid, r0));
	if (fabs(a - b - c) < eps)
		return b + c;
	else
		return simpson(l0, mid) + simpson(mid, r0);
}

int main() {
#ifndef ONLINE_JUDGE
	freopen("in.txt", "r", stdin);
#endif

	double l0, r0;
	scanf("%d%lf", &n, &tht);
	for (int i = 0; i <= n; ++ i)
		scanf("%lf", h + i);
	for (int i = 0; i <= n; ++ i) {
		if (i)
			h[i] += h[i - 1];
		x[i] = h[i] / tan(tht);
	}
	l0 = r0 = x[n];
	for (int i = 0; i < n; ++ i) {
		scanf("%lf", r + i);
		l0 = min(l0, x[i] - r[i]);
		r0 = max(r0, x[i] + r[i]);
	}
	r[n] = 0;
	calc();
	printf("%.2lf\n", simpson(l0, r0) * 2.0);
}