「APIO2018选圆圈」
「APIO2018选圆圈」
题目描述
在平面上,有 \(n\) 个圆,记为 \(c_1, c_2, \ldots, c_n\) 。我们尝试对这些圆运行这个算法:
- 找到这些圆中半径最大的。如果有多个半径最大的圆,选择编号最小的。记为 \(c_i\) 。
- 删除 \(c_i\) 及与其有交集的所有圆。两个圆有交集当且仅当平面上存在一个点,这个点同时在这两个圆的圆周上或圆内。
- 重复上面两个步骤直到所有的圆都被删除。
当 \(c_i\) 被删除时,若循环中第1步选择的圆是 \(c_j\) ,我们说 \(c_i\) 被 \(c_j\) 删除。对于每个圆,求出它是被哪一个圆删除的。
解题思路 :
越抓越痒有理想,\(n^2\) 有信仰。
首先把圆心拿出来建KD树,对于每一棵子树,维护出一个矩形框住这些圆的并,每次删除爆枚整棵树通过判断和这个矩形有没有交来剪枝,最坏复杂度 \(O(n^2)\) ,好像旋转某个角度就卡不掉了。
话说写APIO题卡评测真是爽啊,顺便写篇博客存个KD树板子。
/*program by mangoyang*/
#include<bits/stdc++.h>
#define inf (0x7f7f7f7f)
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
typedef long long ll;
using namespace std;
template <class T>
inline void read(T &x){
int f = 0, ch = 0; x = 0;
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
if(f) x = -x;
}
const int N = 600005;
const double sina = sqrt(2)/2, cosa = sina, eps = 5e-2;
int ans[N], Sgn, rt, n;
inline double sqr(double x){ return x * x; }
inline void chkmax(double &x, double y){ if(y > x) x = y; }
inline void chkmin(double &x, double y){ if(y < x) x = y; }
struct Point{ double x, y, r; int id; } a[N], s[N];
inline bool cmp(Point A, Point B){
if(Sgn == 0) return A.x < B.x;
if(Sgn == 1) return A.y < B.y;
if(Sgn == 2) return A.r == B.r ? (A.id < B.id) : (A.r > B.r);
}
struct Kdtree{
int ch[N][2];
struct Node{
double mx[2], mn[2]; int id;
}T[N];
inline void update(int x){
T[x].mx[0] = a[x].x + a[x].r, T[x].mx[1] = a[x].y + a[x].r;
T[x].mn[0] = a[x].x - a[x].r, T[x].mn[1] = a[x].y - a[x].r;
for(int i = 0; i < 2; i++) if(ch[x][i])
for(int j = 0; j < 2; j++){
chkmax(T[x].mx[j], T[ch[x][i]].mx[j]);
chkmin(T[x].mn[j], T[ch[x][i]].mn[j]);
}
}
inline void build(int &u, int l, int r, int sgn){
if(l > r) return;
int mid = l + r >> 1; u = mid, Sgn = sgn;
nth_element(a + l, a + mid, a + r + 1, cmp);
build(ch[u][0], l, mid - 1, sgn ^ 1);
build(ch[u][1], mid + 1, r, sgn ^ 1), update(u);
}
inline void Delete(int u, Point now){
if(!u || now.x - now.r > T[u].mx[0] || now.x + now.r < T[u].mn[0]
|| now.y - now.r > T[u].mx[1] || now.y + now.r < T[u].mn[1]) return;
if(!ans[a[u].id]){
if(sqr(now.x-a[u].x)+sqr(now.y-a[u].y) <= sqr(now.r+a[u].r) + eps)
ans[a[u].id] = now.id, a[u].x = a[u].y = 0, a[u].r = -inf;
}
Delete(ch[u][0], now), Delete(ch[u][1], now), update(u);
}
}van;
int main(){
read(n);
for(int i = 1, x, y; i <= n; i++){
read(x), read(y), read(a[i].r), a[i].id = i;
a[i].x = (double) x * cosa - y * sina;
a[i].y = (double) x * sina + y * cosa;
}
Sgn = 2, sort(a + 1, a + n + 1, cmp);
for(int i = 1; i <= n; i++) s[i] = a[i];
van.build(rt, 1, n, 0);
for(int i = 1; i <= n; i++)
if(!ans[s[i].id]) van.Delete(rt, s[i]);
for(int i = 1; i <= n; i++) printf("%d ", ans[i]);
return 0;
}
「APIO2018选圆圈」的更多相关文章
- 「APIO2018新家」
「APIO2018新家」 题目描述 五福街是一条笔直的道路,这条道路可以看成一个数轴,街上每个建筑物的坐标都可以用一个整数来表示.小明是一位时光旅行者,他知道在这条街上,在过去现在和未来共有 \(n\ ...
- BZOJ5465 APIO2018选圆圈(KD-Tree+堆)
考虑乱搞,用矩形框圆放KD-Tree上,如果当前删除的圆和矩形有交就递归下去删.为防止被卡,将坐标系旋转一定角度即可.注意eps稍微设大一点,最好开上long double. #include< ...
- [BZOJ5465][APIO2018]选圆圈(KD-Tree)
题意:给你n个圆,每次选择半径最大的,将它和与它相交的圆全部删去,输出每个圆是在哪次被删的. KD树模板题.用一个矩形框住这个圆,就可以直接剪枝了.为了防止被卡可以将点旋转一个角度,为了保险还可以多转 ...
- LG4819/BZOJ2438 「中山市选2011」杀人游戏 Tarjan缩点+概率
问题描述 LG4819 BZOJ2438 题解 发现如果有一些人之间认识关系形成环,只需要问一个人就能把控整个环. \(\mathrm{Tarjan}\)缩点. 缩点之后所有入度为\(0\)的点,必须 ...
- LOJ2586 APIO2018 选圆圈
考前挣扎 KD树好题! 暴力模拟 通过kd树的结构把子树内的圈圈框起来 然后排个序根据圆心距 <= R1+R2来判断是否有交点 然后随便转个角度就可以保持优越的nlgn啦 卡精度差评 必须写ep ...
- 【LG4631】[APIO2018]Circle selection 选圆圈
[LG4631][APIO2018]Circle selection 选圆圈 题面 洛谷 题解 用\(kdt\)乱搞剪枝. 维护每个圆在\(x.y\)轴的坐标范围 相当于维护一个矩形的坐标范围为\([ ...
- LOJ #2585. 「APIO2018」新家
#2585. 「APIO2018」新家 https://loj.ac/problem/2585 分析: 线段树+二分. 首先看怎样数颜色,正常的时候,离线扫一遍右端点,每次只记录最右边的点,然后查询左 ...
- 【APIO2018】选圆圈(平面分块 | CDQ分治 | KDT)
Description 给定平面上的 \(n\) 个圆,用三个参数 \((x, y, R)\) 表示圆心坐标和半径. 每次选取最大的一个尚未被删除的圆删除,并同时删除所有与其相切或相交的圆. 最后输出 ...
- Libre 6007 「网络流 24 题」方格取数 / Luogu 2774 方格取数问题 (网络流,最大流)
Libre 6007 「网络流 24 题」方格取数 / Luogu 2774 方格取数问题 (网络流,最大流) Description 在一个有 m*n 个方格的棋盘中,每个方格中有一个正整数.现要从 ...
随机推荐
- SDUT 3918
Description 这一天希酱又补了一卦,没想到每个人都发到了一张印有整数的牌,现在希酱想要继续占卜的话需要知道每个人手里拿的牌的整数具体是多少,但是她们却打起了哑谜. 穗乃果:我拿到的是 2 ...
- HDU 1214 圆桌会议 (找规律)
题目链接 Problem Description HDU ACM集训队的队员在暑假集训时经常要讨论自己在做题中遇到的问题.每当面临自己解决不了的问题时,他们就会围坐在一张圆形的桌子旁进行交流,经过大家 ...
- JSP分页之结合Bootstrap分页插件进行简单分页
结合Bootstrap的分页插件实现分页,其中策略是每次显示5个按钮,然后根据当前页的不同来进行不同的显示: 1. 当前页<3,如果当前页大于5页就显示前五页,不然就显示1~totalPage. ...
- C++ Boost库 uBLAS 笔记
构造 Vector #include <boost/numeric/ublas/vector.hpp> #include <boost/numeric/ublas/io.hpp> ...
- ASP.NET EF(LINQ/Lambda查询)
EF(EntityFrameWork) ORM(对象关系映射框架/数据持久化框架),根据实体对象操作数据表中数据的一种面向对象的操作框架,底层也是调用ADO.NET ASP.NET MVC 项目会自动 ...
- 使用vscode实现git同步
用了git最方便的就是项目同步管理,回到家打开vscode只需要点击一下pull就能全部同步过来.是不是很方便....毕竟之前我都是拿u盘拷贝回家或者存到云盘再下载下来.. 我这里之前用的是国内的 ...
- Traffic-Server配置(待补充和更新)
Server 5.3.2 测试1.裸盘:remap.configmap http://192.168.227.131 http://192.168.227.131:8080 #traffic_serv ...
- 【读书笔记::深入理解linux内核】内存寻址
我对linux高端内存的错误理解都是从这篇文章得来的,这篇文章里讲的 物理地址 = 逻辑地址 – 0xC0000000:这是内核地址空间的地址转换关系. 这句话瞬间让我惊呆了,根据我的CPU的知识,开 ...
- nvidia tx1使用记录--基本环境搭建
前言 之前有专门写过一篇nvidia tk1使用记录--基本环境搭建,本以为自己有过tk1的经验后,在tx1上搭建和它一样的环境会轻车熟路,结果却是在nvidia tx1上花的时间居然比tk1还多.我 ...
- sicily 1240. Faulty Odometer
Description You are given a car odometer which displays the miles traveled as an integer. The odomet ...