首页 > 其他分享 >CodeForces 887E Little Brother

CodeForces 887E Little Brother

时间:2023-10-16 14:24:07浏览次数:108  
标签:ldb Little %. CodeForces mid 887E calc 5Lf dis

洛谷传送门

CF 传送门

根据初中数学知识,圆心在 \(AB\) 线段的中垂线上。

又因为给定圆与 \(AB\) 线段所在直线不交,所以圆心在中垂线的一端极远处完全包含这个给定圆,在另一端极远处与这个给定圆相离。而具体在哪一端只与圆心在 \(AB\) 的左侧还是右侧有关。

因此可以二分找到与给定圆外切和内切时圆心的坐标。那么一个给定圆只可能挡住一段连续的坐标。扫描线即可。

code
#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mkp make_pair
#define mems(a, x) memset((a), (x), sizeof(a))

using namespace std;
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
typedef long double ldb;
typedef pair<ll, ll> pii;

const int maxn = 100100;

ll A, B, C, D, n, a[maxn], b[maxn], c[maxn];
ldb mx, my;

inline ldb calc(ldb x, ldb y) {
	return sqrtl(x * x + y * y);
}

void solve() {
	scanf("%lld%lld%lld%lld%lld", &A, &B, &C, &D, &n);
	mx = (ldb)(A + C) / 2;
	my = (ldb)(B + D) / 2;
	vector< pair<ldb, int> > vc;
	for (int i = 1; i <= n; ++i) {
		scanf("%lld%lld%lld", &a[i], &b[i], &c[i]);
	}
	if (B == D) {
		swap(mx, my);
		swap(A, B);
		swap(C, D);
		for (int i = 1; i <= n; ++i) {
			swap(a[i], b[i]);
		}
	}
	ldb kk = -(ldb)(A - C) / (B - D);
	ldb bb = my - mx * kk;
	ldb k1 = (ldb)(B - D) / (A - C);
	ldb b1 = my - mx * k1;
	for (int i = 1; i <= n; ++i) {
		if ((A != C && (b[i] - b1) / k1 > a[i]) || (A == C && A > a[i])) {
		// if (0) {
			ldb l = -2e12, r = 2e12;
			while (r - l > 1e-3) {
				ldb mid = (l + r) / 2;
				ldb x = mid, y = kk * mid + bb;
				ldb dis = calc(x - a[i], y - b[i]), R = calc(A - x, B - y);
				// printf("%.5Lf %.5Lf %.5Lf %lld %.5Lf\n", x, y, dis, c[i], R);
				if (dis + c[i] <= R) {
					l = mid;
				} else {
					r = mid;
				}
			}
			// printf("%.5Lf ", l);
			vc.pb(l, 1);
			r = 2e12;
			while (r - l > 1e-3) {
				ldb mid = (l + r) / 2;
				ldb x = mid, y = kk * mid + bb;
				ldb dis = calc(x - a[i], y - b[i]), R = calc(A - x, B - y);
				// printf("%.5Lf %.5Lf %.5Lf %lld %.5Lf\n", x, y, dis, c[i], R);
				if (dis <= R + c[i]) {
					l = mid;
				} else {
					r = mid;
				}
			}
			vc.pb(l, -1);
			// printf("%.5Lf\n", l);
		} else {
			// printf("i: %d\n", i);
			ldb l = -2e12, r = 2e12;
			while (r - l > 1e-3) {
				ldb mid = (l + r) / 2;
				ldb x = mid, y = kk * mid + bb;
				ldb dis = calc(x - a[i], y - b[i]), R = calc(A - x, B - y);
				// printf("%.5Lf %.5Lf %.5Lf %lld %.5Lf\n", x, y, dis, c[i], R);
				if (dis + c[i] >= R) {
					l = mid;
				} else {
					r = mid;
				}
			}
			// printf("%.5Lf ", l);
			vc.pb(l, -1);
			l = -2e12;
			while (r - l > 1e-3) {
				ldb mid = (l + r) / 2;
				ldb x = mid, y = kk * mid + bb;
				ldb dis = calc(x - a[i], y - b[i]), R = calc(A - x, B - y);
				// printf("%.5Lf %.5Lf %.5Lf %lld %.5Lf\n", x, y, dis, c[i], R);
				if (dis >= R + c[i]) {
					l = mid;
				} else {
					r = mid;
				}
			}
			vc.pb(l, 1);
			// printf("%.5Lf\n", l);
		}
	}
	vc.pb(mx, 0);
	sort(vc.begin(), vc.end());
	int x = 0;
	ldb ans = 1e18;
	for (auto p : vc) {
		if (!x) {
			// printf("x, y: %.5Lf %.5Lf\n", p.fst, kk * p.fst + bb);
			ans = min(ans, calc(A - p.fst, B - (kk * p.fst + bb)));
		}
		x += p.scd;
		if (!x) {
			// printf("x, y: %.5Lf %.5Lf\n", p.fst, kk * p.fst + bb);
			ans = min(ans, calc(A - p.fst, B - (kk * p.fst + bb)));
		}
	}
	printf("%.5Lf\n", ans);
}

int main() {
	int T = 1;
	// scanf("%d", &T);
	while (T--) {
		solve();
	}
	return 0;
}

标签:ldb,Little,%.,CodeForces,mid,887E,calc,5Lf,dis
From: https://www.cnblogs.com/zltzlt-blog/p/17767241.html

相关文章

  • Educational Codeforces Round 91 (Rated for Div. 2) A. Three Indices
    给一个\(n\)个整数的排列\(p_1,p_2,\cdots,p_n\),需要找到三个数\(i,j,k\)满足:\(1\leqi<j<k\leqn\)\(p_i<p_j\),\(p_j<p_k\)否则回答不可能。\(key\):若存在上述\(i,j,k\),则存在\(x\)满足\(p_{x-1}<p_{x},p_{x}>p_{x+1......
  • * Codeforces Round 665 (Div. 2) A. Distance and Axis
    有一个点\(A\)在\(OX\)正坐标轴上的\(x\)坐标为\(n\)。需要找到一个点\(B\),使得\(||OB|-|AB||=k\)。现在给出非负整数\(n\)\(k\),你可以执行任意次以下操作:每步操作可以使\(A\)的坐标加一或减一。询问最少需要进过多少次操作使\(B\)可以存在。先假设出......
  • Codeforces Round 903 (Div. 3)
    [比赛链接]A.Don'tTrytoCount直接用string的可加性,每次s+=s相当于翻倍了,因为\(nm<=25\)所以最多翻倍5次。判断什么的直接模拟就行。#include<iostream>#include<algorithm>#include<cmath>#include<cstdio>#include<cstring>#include<cstdlib>#inclu......
  • Codeforces Round 903 (Div. 3) F. Minimum Maximum Distance(图论)
    CodeforcesRound903(Div.3)F.MinimumMaximumDistance思路对标记点更新fg,从0开始进行bfs,更新d1为所有点到0的距离获得到0最远的标记点L,从L开始bfs,更新d2为所有点到L的距离获得距离L最远的标记点R,从R开始bfs,更新d3为所有点到R的距离遍历所有点,这个点与标记点的最大距......
  • CodeForces 1886E I Wanna be the Team Leader
    洛谷传送门CF传送门把题意抽象成,给你长为\(n\)的序列\(a\)和长为\(m\)的序列\(b\),初始有\(m\)个空集合(可重集),\(a\)中的每个元素至多被分到\(m\)个集合中的一个。要求最后第\(i\)个集合\(T_i\)不为空,且\(\forallx\inT_i,x\ge\frac{b_i}{|T|}\)。要求构造......
  • Codeforces Round 671 (Div. 2) A. Digit Game
    \(R\)和\(B\)在玩一个数字游戏,给一个含有\(n\)位的正整数\(x\)。俩人轮流操作,\(R\)先行动。在每一步中,\(R\)可以选择\(x\)中一个未被标记的奇数位置并标记,\(B\)可以选择\(x\)中一个未被标记的偶数位置并标记。当最后只剩下一个未被标记的位置时,让这个数为\(m\)......
  • Codeforces Round 748 (Div. 3) B. Make it Divisible by 25
    给一个正整数\(n\),在一步操作中可以移除\(n\)中的一个。当\(n\)只剩下一位时将不能再操作,如果过程中产生了前导\(0\),则会被自动移除且不耗费操作次数。询问最少需要多少次操作可以使得\(n\)被\(25\)整除。显然一个正整数\(x\)若可以被\(25\)整除,只需要考虑最后......
  • Educational Codeforces Round 116 (Rated for Div. 2) A. AB Balance
    给一个长为\(n\)的字符串\(s\),只包含\(0\)\(1\)两种字符。定义\(AB(s)\)是\(s\)中出现的\(01\)子串个数,\(BA(s)\)是\(s\)中出现的\(10\)子串个数。在一步操作中,可以选择一个字符进行异或。询问最小的操作次数使得\(AB(s)=BA(s)\)。显然连续的\(11\)或连......
  • Codeforces Round 903 (Div. 3) E. Block Sequence(DP)
    CodeforcesRound903(Div.3)E.BlockSequence思路:设dp[i]为当i~n为完美的最少删除次数dp[n]=1,dp[n+1]=0;从后至前对于dp[i]更新若直接删除当前点,则为dp[i+1]+1若不删除则为min(dp[i+a[i]+1],dp[i]);i+a[i]+1为a[i]不能覆盖的位置#defineintlonglong#define......
  • Codeforces Round 903 (Div. 3)
    D题被hack了哭了第一题简单的只用把字符串重复的同时尝试匹配,然后判断就好了,只是需要一点代码能力第二题,也很简单最多剪断3次,就先从小到大排序,然后用最小的,看看大的是他的几倍,如果不是几倍的关系就不可能完成,如果是就算要几次就好了第三题,也很简单,很明显,对于一个格子,在它旋转9......