[LOJ 2022]「AHOI / HNOI2017」队长快跑
[LOJ 2022]「AHOI / HNOI2017」队长快跑
链接
题解
不难看出,除了影响到起点和终点的射线以外,射线的角度没有意义,因为如果一定要从该射线的射出一侧过去,必然会撞到射线
因此,我们可以把射线的方向规约成两类,分成向上与向下的两种。
不难发现,改变射线的方向后,原有的限制条件并未被改变。
要判断一条线是否规约为“垂直向下”,只需判断它的关于P的极角是否在S和T关于P的极角之间。
将所有射线按端点的横坐标排序,依次计算每个端点到S的最短路径上,距离它最近的点nxt。
维护两个队列q1和q2,分别对应上和下两种方向的端点。
初始时在q1和q2中都放入起点坐标。
每次考虑到一个点P(不妨设它是向上的射线),首先看q2的队首到P的连线是否被队列中后一个元素挡住,如果是,则nxt在q2中;否则nxt在q1中。
若nxt在q2中,则不断判断队首是否被后一个挡住,只要被挡住,就向后移动队首的指针,nxt就是最终的队首。
接着,清空q1,并将nxt放入q1中。
若nxt在q1中,则不断判断q1中倒数第二个是否被队尾挡住,只要没被挡住,就向前移动队尾的指针,nxt就是最终的队尾。
最后,无论nxt在哪里,都在q1的末尾加入P。
代码
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N = 1000009;
const int LEN = 1e4;
const double PI = acos(-1);
int n,tot,st[N],head[2],tail[2];
struct Point{
LL x,y; Point *nxt; int pt;
inline Point() {}
inline Point(LL a, LL b):x(a),y(b) {}
inline Point operator + (const Point &P) {return Point(x + P.x, y + P.y);}
inline Point operator - (const Point &P) {return Point(x - P.x, y - P.y);}
inline Point operator * (double t) {return Point(x * t, y * t);}
inline LL operator ^ (const Point &P) {return x * P.x + y * P.y;}
inline LL operator * (const Point &P) {return x * P.y - y * P.x;}
inline bool operator < (const Point &P) const {return x < P.x;}
inline bool operator != (const Point &P) const {return x != P.x || y != P.y;}
inline double len() {return sqrt(x * x + y * y);}
}ss,tt,p[N],vout[N],*que[2][N];
inline int read() {
char c=getchar(); int f=1,ret=0;
while (c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}
while (c<='9'&&c>='0') {ret=ret*10+c-'0';c=getchar();}
return ret * f;
}
inline bool NotInRange(double div, double a, double b) {
if (div >= -PI / 2 && div <= PI / 2) return (a < div || a > PI / 2) && (b < div || b > PI / 2);
else if (div < 0) return a > div && a < PI / 2 && b > div && b < PI / 2;
else return (a > div || a < PI / 2) && (b > div || b < PI / 2);
}
int main() {
n = read(); tt.x = read(); tt.y = read();
for (int i=1;i<=n;i++) {
p[i].x = read(); p[i].y = read();
double r1,r2,r3; scanf("%lf",&r1);
r2 = atan2((ss-p[i]).y, (ss-p[i]).x);
r3 = atan2((tt-p[i]).y, (tt-p[i]).x);
if (NotInRange(r1, r2, r3)) p[i].pt = 1; //射线朝上
else p[i].pt = 0; //射线朝下
}
sort(p+1, p+1+n);
int lim = n; n = 0;
for (int i=1;i<=lim;i++) {
if (p[i].x < ss.x || tt.x < p[i].x) continue;
p[++n] = p[i];
}
p[++n] = tt;
que[0][tail[0] = head[0] = 1] = &ss;
que[1][tail[1] = head[1] = 1] = &ss;
for (int i=1;i<=n;i++) {
int &h1 = head[p[i].pt], &h2 = head[p[i].pt ^ 1], &t1 = tail[p[i].pt], &t2 = tail[p[i].pt ^ 1];
Point **a1 = que[p[i].pt], **a2 = que[p[i].pt ^ 1];
if (h2 < t2 && ((p[i] - *a2[h2]) * (*a2[h2 + 1] - *a2[h2])) * (p[i].pt==1? 1: -1) >= 0) {
while (h2 < t2 && ((p[i] - *a2[h2]) * (*a2[h2 + 1] - *a2[h2])) * (p[i].pt==1? 1: -1) >= 0) {
++h2;
}
p[i].nxt = a2[h2];
a1[h1 = t1 = t1 + 1] = a2[h2];
} else {
while (h1 < t1 && ((p[i] - *a1[t1 - 1]) * (*a1[t1] - *a1[t1 - 1])) * (p[i].pt==1? 1: -1) >= 0) {
--t1;
}
p[i].nxt = a1[t1];
}
a1[++t1] = &p[i];
}
double ans = 0;
for (Point *cur=&p[n],*last;*cur!=ss;) {
last = cur; cur = cur->nxt;
ans += (*cur - *last).len();
}
printf("%.10lf\n",ans);
return 0;
}
[LOJ 2022]「AHOI / HNOI2017」队长快跑的更多相关文章
- loj#2020 「AHOI / HNOI2017」礼物 ntt
loj#2020 「AHOI / HNOI2017」礼物 链接 bzoj没\(letex\),差评 loj luogu 思路 最小化\(\sum\limits_1^n(a_i-b_i)^2\) 设改变 ...
- loj #2023. 「AHOI / HNOI2017」抛硬币
#2023. 「AHOI / HNOI2017」抛硬币 题目描述 小 A 和小 B 是一对好朋友,他们经常一起愉快的玩耍.最近小 B 沉迷于**师手游,天天刷本,根本无心搞学习.但是已经入坑了几个 ...
- loj #2021. 「AHOI / HNOI2017」大佬
#2021. 「AHOI / HNOI2017」大佬 题目描述 人们总是难免会碰到大佬.他们趾高气昂地谈论凡人不能理解的算法和数据结构,走到任何一个地方,大佬的气场就能让周围的人吓得瑟瑟发抖,不敢 ...
- LOJ#2019. 「AHOI / HNOI2017」影魔
题意: 在一个序列中 如果有一个子区间 它有一个端点是区间最大值 另一个端点不是这个区间的次大值 就会有p2的贡献 它两个端点分别是最大值次大值 就会有p1的贡献 我们发现这两个条件有一个重合的部分 ...
- loj#2020. 「AHOI / HNOI2017」礼物
题意:给定xy数组求 \(\sum_{i=0}^{n-1}(x_i+y_{(i+k)\modn}+c)^2\) 题解:先化简可得 \(n*c^2+2*\sum_{i=0}^{n-1}x_i-y_i+\ ...
- 「AHOI / HNOI2017」单旋
「AHOI / HNOI2017」单旋 题目链接 H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据结构,因为代码好写,功能多,效率高,掌握这种 ...
- Loj #2495. 「AHOI / HNOI2018」转盘
Loj #2495. 「AHOI / HNOI2018」转盘 题目描述 一次小 G 和小 H 原本准备去聚餐,但由于太麻烦了于是题面简化如下: 一个转盘上有摆成一圈的 \(n\) 个物品(编号 \(1 ...
- Loj #2494. 「AHOI / HNOI2018」寻宝游戏
Loj #2494. 「AHOI / HNOI2018」寻宝游戏 题目描述 某大学每年都会有一次 Mystery Hunt 的活动,玩家需要根据设置的线索解谜,找到宝藏的位置,前一年获胜的队伍可以获得 ...
- 「AHOI / HNOI2017」影魔
「AHOI / HNOI2017」影魔 题目描述 解决这类比较复杂的区间贡献问题关键在于找到计算的对象. 比如这道题,我们计算的对象就是区间中间的最大值. 对于点\(i\),我们找到左边第一个比他大的 ...
随机推荐
- npm使用淘宝镜像安装包
npm使用registry这个属性指定仓库,因此配置这个属性即可.修改npm配置属性的几种方法详见官方文档. 这里只贴出修改registry的方法,以下三种任意一种即可: 修改~/.npmrc文件(没 ...
- ACM学习历程—ZOJ 3861 Valid Pattern Lock(dfs)
Description Pattern lock security is generally used in Android handsets instead of a password. The p ...
- codevs 3049 舞蹈家怀特先生
题目描述 Description 怀特先生是一个大胖子.他很喜欢玩跳舞机(Dance Dance Revolution, DDR),甚至希望有一天人家会脚踏“舞蹈家怀特先生”.可惜现在他的动作根本不能 ...
- bzoj 4310 跳蚤 —— 后缀数组+二分答案+贪心
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4310 二分答案——在本质不同的子串中二分答案! 如果二分到的子串位置是 st,考虑何时必须分 ...
- SQL Server 将查询的结果生成insert语句
1.将查询的结果插入到一张新表(yangTest 表系统会自动生成)select Area, District, RoadName, StationName, PathDirection, Stati ...
- xpath技术,用在dom4j中
title: xPath语法应用 tags: xPath,dom4j grammar_cjkRuby: true --- 在dom4j中,会使用到xPath技术. 在项目中导入 jaxen-1.1-b ...
- AI-Info-Micron-Insight:高速数据:第四次工业革命的助推引擎
ylbtech-AI-Info-Micron-Insight:高速数据:第四次工业革命的助推引擎 1.返回顶部 1. 高速数据:第四次工业革命的助推引擎 第四次工业革命已然来临,因为数字技术几乎连接了 ...
- oracle 日期问题 网上找到自己查阅时方便
第一部分:oracle sql日期比较: oracle sql日期比较:在今天之前: select*from up_date whereupdate< to_date('2007-09-07 0 ...
- [hdu3853]LOOPS(概率dp)
题意:迷宫是一个R*C的布局,每个格子中给出停留在原地,往右走一个,往下走一格的概率,起点在(1,1),终点在(R,C),每走一格消耗两点能量,求出最后所需要的能量期望. 解题关键:概率dp反向求期望 ...
- day1 java基础
常见的dos命令 盘符: 进入指定的盘符下. dir : 列出当前目录下的文件以及文件夹 md : 创建目录 rd : 删除目录 注意:rd不能删除非空的文件夹,而且只能用于删除文件夹. cd ...