qwq纪念AC450

一开始想这个题想复杂了。

首先,正解的做法是比较麻烦的。

qwqq

那么就不如来一点暴力的东西,看到平面上点的距离的题,不难想到\(KD-Tree\)

我们用类似平面最近点对那个题一样的维护方式,对于一个子树内部,分别维护每一个维度的最大值和最小值,还有半径的最大值。

然后\(sort\)一遍,从半径大到小依次\(query\),每次\(query\)的时候,对于当前点,合法的条件是他和目标点的距离要小于等于两个圆的半径的和。

那么对于子树的估价函数,我们默认如果当前目标点的当前维度的范围是\(mn-mx\)之间的话,距离就是\(0\),否则取一个最短距离,然后和上述要求一样的比较方式。进行剪枝。

这样就能直接通过洛谷的数据了,但是由于\(loj\)的数据比较强,所以还需要将原来的点绕着一个点旋转一下。

那么假设我们旋转的角度是\(\phi\)

那么我们需要将原来那两个坐标乘上一个矩阵

cos -sin
sin cos

直接上代码了

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<cmath>
#include<map>
#include<set>
#define pb push_back
#define mk make_pair
#define ll long long
#define lson ch[x][0]
#define rson ch[x][1]
#define double long double
#define int long long using namespace std; inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
} const int maxn = 4e5+1e2;
const double phi = 1.04719755116;
const double eps = 1e-4; struct KD{
double d[2],mx[2],mn[2];
double bj,mr;
int l,r;
int num;
}; KD now,t[maxn];
int root,ymh,n,m;
int ans[maxn]; struct Node{
double x,y;
double r;
int num;
}; Node a[maxn]; bool cmp(Node a,Node b)
{
if (a.r==b.r) return a.num<b.num;
return a.r>b.r;
} bool operator <(KD a,KD b)
{
return a.d[ymh]<b.d[ymh];
} void up(int root)
{
for (int i=0;i<=1;i++)
{
if (t[root].l) t[root].mn[i]=min(t[root].mn[i],t[t[root].l].mn[i]);
if (t[root].l) t[root].mx[i]=max(t[root].mx[i],t[t[root].l].mx[i]);
if (t[root].l) t[root].mr=max(t[root].mr,t[t[root].l].mr);
if (t[root].r) t[root].mr=max(t[root].mr,t[t[root].r].mr);
if (t[root].r) t[root].mn[i]=min(t[root].mn[i],t[t[root].r].mn[i]);
if (t[root].r) t[root].mx[i]=max(t[root].mx[i],t[t[root].r].mx[i]);
}
} void build(int &x,int l,int r,int dd)
{
ymh = dd;
int mid = l+r >> 1;
x=mid;
nth_element(t+l,t+mid,t+r+1);
for (int i=0;i<=1;i++) t[x].mn[i]=t[x].mx[i]=t[x].d[i];
t[x].mr=t[x].bj;
if (l<x) build(t[x].l,l,mid-1,dd^1);
if (x<r) build(t[x].r,mid+1,r,dd^1);
up(x);
} inline double getdis(int x)
{
double ans=0;
for (int i=0;i<=1;i++) ans=ans+(t[x].d[i]-now.d[i])*(t[x].d[i]-now.d[i]);
return ans;
} inline double calc(int x)
{
double ans=0;
for (int i=0;i<=1;i++)
{
double tmp=0;
if (now.d[i]>=t[x].mn[i] && now.d[i]<=t[x].mx[i]) tmp=0;
else tmp=min((t[x].mn[i]-now.d[i])*(t[x].mn[i]-now.d[i]),(t[x].mx[i]-now.d[i])*(t[x].mx[i]-now.d[i]));
ans=ans+tmp;
}
return ans;
} void query(int x)
{
//cout<<now.num<<endl;
//cout<<x<<" "<<t[x].l<<" "<<t[x].r<<" "<<t[x].mr<<" "<<t[x].d[1]<<endl;;
if (!x) return;
double d = getdis(x);
double d1 = calc(t[x].l);
double d2 = calc(t[x].r);
//cout<<d1<<" "<<(t[t[x].l].mr+now.bj)<<" "<<d2<<endl;
if (!ans[t[x].num] && (t[x].bj+now.bj)*(t[x].bj+now.bj)-d>=-eps) ans[t[x].num]=now.num;
if ((t[t[x].l].mr+now.bj)*(t[t[x].l].mr+now.bj)-d1>=-eps) query(t[x].l);
if ((t[t[x].r].mr+now.bj)*(t[t[x].r].mr+now.bj)-d2>=-eps) query(t[x].r);
} signed main()
{
n=read();
for (int i=1;i<=n;i++)
{
double x=read(),y=read(),r=read();
double tmp = x;
x=cos(phi)*x-sin(phi)*y;
y=sin(phi)*tmp+cos(phi)*y;
t[i].num=i;
t[i].d[0]=x;
t[i].d[1]=y;
t[i].bj=r;
a[i].x=x;
a[i].y=y;
a[i].num=i;
a[i].r=r;
//printf("%.2lf %.2lf %.2lf\n",x,y,r);
//cout<<endl;
}
build(root,1,n,0);
//cout<<"********"<<endl;
sort(a+1,a+1+n,cmp);
for (int i=1;i<=n;i++)
{
if (ans[a[i].num]) continue;
now.d[0]=a[i].x;
now.d[1]=a[i].y;
now.bj=a[i].r;
now.num=a[i].num;
query(root);
//out<<"*******"<<endl;
}
for (int i=1;i<=n;i++) cout<<ans[i]<<" ";
return 0;
}

洛谷4631 [APIO2018] Circle selection 选圆圈 (KD树)的更多相关文章

  1. 【LG4631】[APIO2018]Circle selection 选圆圈

    [LG4631][APIO2018]Circle selection 选圆圈 题面 洛谷 题解 用\(kdt\)乱搞剪枝. 维护每个圆在\(x.y\)轴的坐标范围 相当于维护一个矩形的坐标范围为\([ ...

  2. [APIO2018] Circle selection 选圆圈(假题解)

    题面 自己去\(LOJ\)上找 Sol 直接排序然后\(KDTree\)查询 然后发现\(TLE\)了 然后把点旋转一下,就过了.. # include <bits/stdc++.h> # ...

  3. [Luogu4631][APIO2018] Circle selection 选圆圈

    Luogu 题目描述 在平面上,有 \(n\) 个圆,记为 \(c_1, c_2,...,c_n\) .我们尝试对这些圆运行这个算法: \(1\).找到这些圆中半径最大的.如果有多个半径最大的圆,选择 ...

  4. [APIO2018] Circle selection 选圆圈

    Description 给出 \(n\) 个圆 \((x_i,y_i,r_i)\) 每次重复以下步骤: 找出半径最大的圆,并删除与这个圆相交的圆 求出每一个圆是被哪个圆删除的 Solution \(k ...

  5. luogu P4631 [APIO2018] Circle selection 选圆圈

    传送门 那个当前半径最大的圆可以用堆维护.这道题一个想法就是优化找和当前圆有交的圆的过程.考虑对于所有圆心建KD-tree,然后在树上遍历的找这样的点.只要某个点子树内的点构成的矩形区域到当前圆心的最 ...

  6. LOJ 2586 「APIO2018」选圆圈——KD树

    题目:https://loj.ac/problem/2586 只会 19 分的暴力. y 都相等,仍然按直径从大到小做.如果当前圆没有被删除,那么用线段树把 [ x-r , x+r ] 都打上它的标记 ...

  7. 【洛谷5439】【XR-2】永恒(树链剖分,线段树)

    [洛谷5439][XR-2]永恒(树链剖分,线段树) 题面 洛谷 题解 首先两个点的\(LCP\)就是\(Trie\)树上的\(LCA\)的深度. 考虑一对点的贡献,如果这两个点不具有祖先关系,那么这 ...

  8. 洛谷P4630 [APIO2018] Duathlon 铁人两项 【圆方树】

    题目链接 洛谷P4630 题解 看了一下部分分,觉得树的部分很可做,就相当于求一个点对路径长之和的东西,考虑一下能不能转化到一般图来? 一般图要转为树,就使用圆方树呗 思考一下发现,两点之间经过的点双 ...

  9. [APIO2018]Circle selection

    https://www.zybuluo.com/ysner/note/1257597 题面 在平面上,有\(n\)个圆,记为\(c_1,c_2,...,c_n\).我们尝试对这些圆运行这个算法: 找到 ...

随机推荐

  1. Mysql索引最佳实践笔记0524

    #mysql5.7 innodb默认存储引擎 一.关于索引二.最佳实践三.避坑实践 一.关于索引 1.索引的作用 -提高查询效率 -数据分组.排序 -避免回表查询 -优化聚集查询 -用于多表join关 ...

  2. 移动端 uni-app 滑动事件 精确判断手指滑动方向

    移动端根据手指滑动操作判断滑动方向 设计思路: 1.根据移动端touchstart和touchend方法获取手指触摸屏幕的开始坐标和结束坐标 2.根据两个坐标计算与水平方向的夹角 3.根据夹角判断当前 ...

  3. Nginx+Tomcat+Memcached实现session共享

    实验环境: server1:nginx tomcat memcached server2:tomcat memcached Session是指一个终端用户与交互系统进行通信的时间间隔,通常指从注册进入 ...

  4. 为开源项目 go-gin-api 增加后台任务模块

    目录 任务管理界面 (WEB) 任务调度器 任务执行器 小结 推荐阅读 任务管理界面 (WEB) 支持在 WEB 界面 中对任务进行管理,例如:新增任务.编辑任务.启用/禁用任务.手动执行任务 等. ...

  5. 微前端框架single-spa初探

    前言 最近入职的一家公司采用single-spa这个微前端框架,所以自学了此框架. single-spa这个微前端框架虽然有中文文档,但是有些零散和晦涩. 所以我想在学习之余,写篇博客拉平一下这个学习 ...

  6. Java最大栈深度有多大?-从一道面试题开始学习JVM

    一.问题:Java最大支持栈深度有多大? 1.分析 有JVM的内存结构我们可知: 随着线程栈的大小越大,能够支持越多的方法调用,也即是能够存储更多的栈帧: 局部变量表内容越多,那么栈帧就越大,栈深度就 ...

  7. 洛谷P1925 最大划分乘积的数学解法

    题目 最大划分乘积 题解 这道题用到一点导数和数论的知识,很容易看出这道题是求函数 \[f(x)=(\frac{n}{x})^{x} \] ( \(x\) 为正整数)的最大值.我们可以对 \(ln(f ...

  8. MongoDB(1)- 入门介绍

    MongoDB 数据库 MongoDB 是一个文档数据库,旨在简化开发和扩展 MongoDB 中的记录是一个文档 Document,是由字段和值对组成的数据结构 MongoDB 文档类似于 JSON ...

  9. 知乎大佬图文并茂的epoll讲解,看不懂的去砍他

    select.poll.epoll的文章很多,自己也看过不少经典好文.不过第一次看到讲的如此通俗易懂.又图文并茂的.因此拿来分享下,供后续翻看学习. 原文链接:https://zhuanlan.zhi ...

  10. jdbc核心技术-宋红康

    视频地址 JDBC核心技术 第1章:JDBC概述 1.1 数据的持久化 持久化(persistence):把数据保存到可掉电式存储设备中以供之后使用.大多数情况下,特别是企业级应用,数据持久化意味着将 ...