首页 > 其他分享 >ABC263Ex Intersection 2 题解

ABC263Ex Intersection 2 题解

时间:2024-04-16 17:59:06浏览次数:23  
标签:fi le ABC263Ex int 题解 double frac Intersection se

ABC263Ex

Problem

给定 \(N\) 条不平行的直线 \(A_ix+B_iy+C=0\),\(N\) 条直线总共会有 \(\frac{N(N-1)}{2}\) 个交点(包含在同一个位置的点,即相同位置算不同的点),找出距离原点第 \(K\) 近的交点的距离。

$2\le N\le 5\times 10^4 $,\(1\le K\le \frac{N(N-1)}{2}\),$-1000\le|A_i|,|B_i|,|C_i|\le1000(1\le i\le N) $,保证 \(A_i\),\(B_i\) 均非零。

Sol

发现题目点的个数其实是有 \(\mathcal{O}(n^2)\) 个的,显然不好直接统计,考虑二分答案。

具体地,二分出距离 \(r\),变为求原点与交点的距离 \(\le r\) 的个数。思考直线 \(L_i\) 与直线 \(L_j\) 的交点会被统计的条件。可以画出一个 \(x^2 +y^2 = r^2\) 的圆,即变为交点在圆内。由于不好直接考虑 \(L_i\),\(L_j\) 的交点,可以算出所有直线与圆的交点 \((x_{i1}, y_{i1}), (x_{i2}, y_{i2})\)。将两个交点都转化为一个连向原点的与 \(x\) 轴的夹角,这样可以得到一个度数区间 \([l_i, r_i](0\le l_i\le r_i<2\pi)\),然后两条直线满足交点的条件就是这两个度数区间相交但不包含。统计相交但不包含的区间对数可以通过按左端点从小到大排序后用树状数组统计。

时间复杂度:\(\mathcal{O(n\log n\log \frac{V}{\text{eps}})}\)。这里的 \(\text{eps}\) 是程序中设置的精度。

\(x^2 + y^2 = R^2\) 与 \(Ax + By + C = 0\) 的交点。

  • \(B \neq 0\) 时,有 \(y = -\frac{Ax + C}{B}\):

\[x^2 + \frac{A^2x^2 + C^2 + 2ACx}{B^2} = R^2 \]

\[(\frac{A^2 + B^2}{B^2})x^2 + \frac{2AC}{B^2} x+\frac{C^2}{B^2} - R^2 = 0 \]

\[\begin{aligned} x &= \dfrac{ -\dfrac{2AC}{B^2} \pm \sqrt{\frac{4A^2C^2}{B^4} - 4\cdot\frac{A^2+B^2}{B^2}\cdot\frac{C^2-B^2R^2}{B^2} } } { 2\cdot \dfrac{A^2 + B^2}{B^2} } \\ &= \dfrac{-AC \pm \sqrt{A^2C^2 - (A^2 + B^2)\cdot(C^2-B^2R^2))}} {A^2 + B^2} \\ &= \dfrac{-AC \pm \sqrt{(A^2+B^2)B^2R^2 - B^2C^2}} {A^2 + B^2} \end{aligned} \]

$ y $ 可以用 $\frac{Ax + C}{B} $ 计算。

  • \(B = 0\) 时,\(x = -\frac{C}{A}\)。

\[y^2 = R^2 - \frac{C^2}{A^2} \]

\[y = \pm \sqrt{R^2 - \frac{C^2}{A^2}} \]

Code
#include<bits/stdc++.h>
#define ll long long
#define sz(a) ((int) (a).size())
#define vi vector < int >
#define pb emplace_back
using namespace std;
#define fi first
#define se second
#define double long double
const double eps = 1e-10;
int n, k;
double a[50010], b[50010], c[50010], lsh[100010];
pair < double, double > tmp[50010];
struct node {
  int x, y, c;
} pos[50010];
struct BIT {
  int n;
  vi v;
  BIT(int _n = 100000) : v(_n + 10) { n = _n; }
  void add(int x, int y) {
    for(; x <= n; x += x & -x)
      v[x] += y;
  }
  int ask(int x) {
    int ret = 0;
    for(; x; x -= x & -x)
      ret += v[x];
    return ret;
  }
  int ask(int x, int y) { return ask(y) - ask(x - 1); }
} ;
double sqr(double x) { return x * x; }
double deg(double a, double b) {
  return atan2(a, b);
}
pair < double, double > calc(double a, double b, double c, double R) {
  double sa = sqr(a), sb = sqr(b), sc = sqr(c), sr = sqr(R);
  pair < double, double > p1, p2;
  if(fabs(b) > eps) {
    double delta = (sa + sb) * sb * sr - sb * sc;
    if(delta < 0)
      return make_pair(1011451423, 1011451423);
    p1.fi = (-a * c + sqrt(delta)) / (sa + sb);
    p2.fi = (-a * c - sqrt(delta)) / (sa + sb);
    p1.se = -(a * p1.fi + c) / b;
    p2.se = -(a * p2.fi + c) / b;
  }
  else {
    p1.fi = p2.fi = -c / a;
    p1.se = sqrt(sr - sc / sa);
    p2.se = -p1.se;
  }
  double l = deg(p1.fi, p1.se), r = deg(p2.fi, p2.se);
  if(l > r)
    swap(l, r);
  return make_pair(l, r);
}
map < pair < int, int >, int > mp;
bool check(double mid) {
  int num = 0;
  for(int i = 1; i <= n; ++i) {
    pair < double, double > ret = calc(a[i], b[i], c[i], mid);
    if(ret.fi != 1011451423 || ret.se != 1011451423)
      ++num, tmp[num] = ret, lsh[2 * num - 1] = tmp[num].fi, lsh[2 * num] = tmp[num].se;
  }
  sort(lsh + 1, lsh + 2 * num + 1);
  int len = unique(lsh + 1, lsh + 2 * num + 1) - lsh - 1;
  mp.clear();
  for(int i = 1; i <= num; ++i) {
    pos[i].x = lower_bound(lsh + 1, lsh + len + 1, tmp[i].fi) - lsh;
    pos[i].y = lower_bound(lsh + 1, lsh + len + 1, tmp[i].se) - lsh;
    ++mp[make_pair(pos[i].x, pos[i].y)];
  }
  int m = 0;
  for(auto it : mp)
    ++m, pos[m].x = it.fi.fi, pos[m].y = it.fi.se, pos[m].c = it.se;
  sort(pos + 1, pos + m + 1, [](node a, node b) { return a.x != b.x ? a.x < b.x : a.y < b.y; });
  BIT T(len);
  int cnt = 0;
  for(int i = 1; i <= m; ++i) {
    cnt += T.ask(pos[i].x, pos[i].y);
    T.add(pos[i].y, pos[i].c);
  }
  return cnt >= k;
}
int main() {
  ios :: sync_with_stdio(false);
  cin.tie(0); cout.tie(0);
  cin >> n >> k;
  for(int i = 1; i <= n; ++i)
    cin >> a[i] >> b[i] >> c[i];
  double L = eps, R = 5e6;
  while(R - L > eps) {
    double mid = (L + R) / 2;
    if(check(mid))
      R = mid;
    else
      L = mid;
  }
  cout << fixed << setprecision(10) << L << "\n";
  return 0;
}

标签:fi,le,ABC263Ex,int,题解,double,frac,Intersection,se
From: https://www.cnblogs.com/Pengzt/p/-/solution-ABC263Ex

相关文章

  • CF154C Double Profiles 题解
    CF154CDoubleProfiles题解思路解析题目说的很明白,求有多少个无序点对\((i,j)\),使得与\(i\)直接相连的点集与直接与\(j\)相连的点集完全相等。我们想到如果直接判断每个\(i,j\)肯定会超时,所以我们想把每一个与任意一点直接相连的点集进行压缩,可以想到使用字符串哈希的......
  • [题解] [CCPC陕西省赛2022 D题] Hash
    [CCPC陕西省赛2022D题]Hash题目描述给定一个字符串\(S\),按照如下方法获取\(S\)的哈希值://LanguageC++14longlongmod=5999993;longlonggethas(strings){longlongret=0;for(charc:s)ret=(ret*29+(c-'a'+1))%mod;returnret;}找到一个......
  • CF1097F Alex and a TV Show 题解
    题目链接点击打开链接题目解法很牛的套路啊!看到集合并,且只要求奇偶性的问题,第一个想到\(bitset\)\(1,2,4\)操作都是好维护的,关键是第\(3\)个操作看到$\gcd$,首先想到莫反令\(c_{x,i}\)为集合\(x\)中数\(i\)的出现次数则\(c_{x,i}=\sum\limits_{i|j}\sum\limit......
  • 如何写好一篇题解?
    为什么要写题解?首先要清楚知道一点,写题解不仅是帮助别人在做题遇到困难时指明方向,更是提升自己的最快途径。经常有人问我:“如何提升自己的程序设计能力”。我都会回答:“写题解”。写题解可以帮助你彻底掌握某一个知识点。无论一道题目是否是你独立写出来的,你都应该去尝试写题解......
  • 取胜 题解
    很厉害的题,记录下题意是随机一棵无根树,随一个根,每条边存在(能走通)的概率为\(p\),以根为起点,每次一方选择当前点的一个能走通的儿子走过去,问先手必胜的概率.容易发现可以当成有根树.用\(F(x)\)和\(G(x)\)表示必胜树和必败树的egf,有\[\begin{cases}F(x)=xe^{F(x)}\le......
  • 开机后mysql服务未启动问题解决
    问题:mysql的启动类型设置了自动,但是电脑开机后还是需要手动启动。 解决方法:一、Win+R快捷键弹出运行框 二、输入regedit后回车 三、地址栏内输入计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control后回车 四、找到Control入径后,新建一个名称为ServicesPipe......
  • [题解][2021-2022年度国际大学生程序设计竞赛第10届陕西省程序设计竞赛] Type The Str
    题目描述给定n个字符串,有以下几种操作:打出一个字符,花费1。删除一个字符,花费1。复制并打出一个之前打出过的字符串,花费k。求打出所有n个字符串的最小花费。(注意,打出顺序和字符串输入的顺序不必相同)题解显然,操作3需要算字符串的最长公共子序列来处理。这个问题可以转换为......
  • P4298 [CTSC2008] 祭祀 题解
    P4298[CTSC2008]祭祀题解给定DAG,求最长反链长度,最长反链方案,有多少个点可以成为反链上的点。Case1熟知Dilworth定理:偏序集的最长反链的长度等于最小链划分。因为偏序集有传递性,所以我们也需要对DAG做一遍传递闭包。这样可以套用Dilworth定理,最小链划分等于点数减......
  • [题解][2021-2022年度国际大学生程序设计竞赛第10届陕西省程序设计竞赛] Hash
    题目描述给定字符串T,要求求字符串S,满足以下条件:S是T的前缀S和T运行某段代码的哈希值相同(代码见下)T只包含小写字母S和T的长度差不超过50哈希代码://LanguageC++14longlongmod=5999993;longlonggethas(strings){longlongret=0;for(charc:s)ret=......
  • PGSQL 问题解决
    1服务无法启动 这里更改安装目录bin下面例如E:\WorkingSoftware\PostgreSql\16\bin更改权限,下面都改下 2  安装时提示database出错,就初始化下执行以下命令E:\WorkingSoftware\PostgreSql\16\bin\pg_ctl.exe-DE:\WorkingSoftware\PostgreSql\16\dat......