CF70D(动态凸包)
CF70D(动态凸包)
给出q(<=1e5)个询问,每次在加上一个点,维护凸包,或者询问某个点是否在凸包内(在边上也算)。
听说可以用cdq做……但是并不会。我等蒟蒻只会用平衡树做。
首先,假设已经维护出了某个点按照极角排序的凸包,那么对于加入的一个点,我们首先要查询它是在凸包内还是凸包外(这个功能也可以用于题目中的查询)。O表示极角排序的原点,next表示极角排序的下一个点,pre则表示上一个点:
那么,如果p在凸包外,a\(\times\)b就是正数,若p在凸包内a\(\times\)b则是非正整数。
接着,我们要维护凸包。维护凸包依然要查询next和pre:

类似于gramham,不断通过删除next和pre维护凸包凸性。形象理解一下,可以看成p点伸出了两个筷子,不停尝试夹住凸包(凸包:喵喵喵?)
注意判断点是否在凸包内时,有个小坑点。O点必须选择在凸包内,既不能选择在凸包外也不能选择在凸包的边上。
#include <set>
#include <cmath>
#include <cstdio>
using namespace std;
typedef long long LL;
const LL maxn=1e5+5;
double ox=0, oy=0;
struct Point{
LL op, x, y; double angle;
Point (LL a=0, LL b=0):x(a), y(b){}
void getangle(){ angle=atan2(y-oy, x-ox); }
}p[maxn];
Point operator +(const Point &a, const Point &b){ return Point(a.x+b.x, a.y+b.y); }
Point operator -(const Point &a, const Point &b){ return Point(a.x-b.x, a.y-b.y); }
LL operator *(const Point &a, const Point &b){ return a.x*b.y-a.y*b.x; }
bool operator <(const Point &a, const Point &b){ //a是否在b的逆时针处
return a.angle<b.angle; }
LL q;
typedef multiset<Point>::iterator iter;
typedef Point Vector;
multiset<Point> s;
iter nxt(iter x){ return x==--s.end()?s.begin():++x; }
iter pre(iter x){ return x==s.begin()?--s.end():--x; }
bool in(iter x){
if (s.size()<3) return false;
return (*nxt(x)-*x)*(*pre(x)-*x)<=0; //叉积(是不是神仙操作)
}
void add(Point &x){
iter it=s.insert(x);
if (s.size()<=3) return;
if (in(it)){ s.erase(it); return; }
while (s.size()>3&&(*nxt(it)-*it)*(*nxt(nxt(it))-*nxt(it))<=0) //神仙操作*2
s.erase(nxt(it)); //注意加上=0以后,要判断size以免遇到两个点的情况
while (s.size()>3&&(*pre(it)-*it)*(*pre(pre(it))-*pre(it))>=0) //神仙操作*3
s.erase(pre(it));
}
bool query(Point &x){
iter it=s.insert(x); bool flag;
if (in(it)) flag=true; else flag=false;
s.erase(it); return flag;
}
int main(){
scanf("%lld", &q);
for (LL i=0; i<q; ++i)
scanf("%lld%lld%lld", &p[i].op, &p[i].x, &p[i].y);
Point t=p[0]+p[1]+p[2]; ox=(double)t.x/3; oy=(double)t.y/3;
//这样确定原点,保证原点不在凸包的边上
//若不这样:例子:A(-1, 0) B(1, 0) Q(4, 0)
for (LL i=0; i<q; ++i) p[i].getangle(); //确定极角
for (LL i=0; i<q; ++i){
if (p[i].op==1) add(p[i]);
else puts(query(p[i])?"YES":"NO");
}
return 0;
}
CF70D(动态凸包)的更多相关文章
- CF70D Professor's task(动态凸包)
题面 两种操作: 1 往点集S中添加一个点(x,y); 2 询问(x,y)是否在点集S的凸包中. 数据保证至少有一个2操作, 保证刚开始会给出三个1操作, 且这三个操作中的点不共线. 题解 动态凸包板 ...
- 【BZOJ 2300】 2300: [HAOI2011]防线修建 (动态凸包+set)
2300: [HAOI2011]防线修建 Description 近来A国和B国的矛盾激化,为了预防不测,A国准备修建一条长长的防线,当然修建防线的话,肯定要把需要保护的城市修在防线内部了.可是A国上 ...
- BZOJ 2300: [HAOI2011]防线修建( 动态凸包 )
离线然后倒着做就变成了支持加点的动态凸包...用平衡树维护上凸壳...时间复杂度O(NlogN) --------------------------------------------------- ...
- [NOI2007]货币兑换Cash(DP+动态凸包)
第一次打动态凸包维护dp,感觉学到了超级多的东西. 首先,set是如此的好用!!!可以通过控制一个flag来实现两种查询,维护凸包和查找斜率k 不过就是重载运算符和一些细节方面有些恶心,90行解决 后 ...
- BZOJ [HAOI2011]防线修建(动态凸包)
听说有一种很高端的东西叫动态凸包维护dp就像学一下,不过介于本人还不会动态凸包就去学了下,还是挺神奇的说,维护上下凸包的写法虽然打得有点多不过也只是维护复制黏贴的事情而已罢了. 先说下动态凸包怎么写吧 ...
- 【BZOJ 1701】Cow School(斜率优化/动态凸包/分治优化)
原题题解和数据下载 Usaco2007 Jan 题意 小牛参加了n个测试,第i个测试满分是\(p_i\),它的得分是\(t_i\).老师去掉\(t_i/p_i\)最小的d个测试,将剩下的总得分/总满分 ...
- Code Chef TSUM2(动态凸包+点分治)
题面 传送门 题解 真是毒瘤随机化算法居然一分都不给 首先这种树上的题目一般想到的都是点分 我们考虑如何统计经过当前点的路径的贡献,设当前点\(u\)在序列中是第\(c\)个,那么一条路径的贡献就是 ...
- codeforces 70 D. Professor's task 动态凸包
地址:http://codeforces.com/problemset/problem/70/D 题目: D. Professor's task time limit per test 1 secon ...
- 【bzoj2300】【Luogu P2521】 [HAOI2011]防线修建 动态凸包,平衡树,Set
一句话题意:给你一个凸包,每次可以插入一个点或者询问周长. 动态凸包裸题嘛,用\(Set\)实现.最初每个点坐标做乘三处理,便于取初始三角形的重心作为凸包判定原点. #include <bits ...
随机推荐
- 分析诊断工具之一:MYSQL性能查看(多指标)
网上有很多的文章教怎么配置MySQL服务器,但考虑到服务器硬件配置的不同,具体应用的差别,那些文章的做法只能作为初步设置参考,我们需要根据自己的情况进行配置优化,好的做法是MySQL服务器稳定运行了一 ...
- linux下面的df命令
linux中df命令的功能是用来检查linux服务器的文件系统的磁盘空间占用情况.可以利用该命令来获取硬盘被占用了多少空间,目前还剩下多少空间等信息. 1.命令格式: df [选项] [文件] 2.命 ...
- win10/server2019 系统安装 详解
https://www.microsoft.com/zh-cn/software-download/windows10 https://go.microsoft.com/fwlink/?LinkId= ...
- OpenCV 视频监控(Video Surveilance)的算法体系
如前面说到的,OpenCV VS提供了6组算法的接口,分别是:前景检测.新目标检测.目标跟踪.轨迹生成.跟踪后处理.轨迹分析,除了轨迹生成用于轨迹数据的保存以外,其他5个部分都是标准的视频监控算法体系 ...
- Git学习笔记(三)远程库(GitHub)协同开发,fork和忽略特殊文件
远程库 远程库,通俗的讲就是不再本地的git仓库!他的工作方式和我们本地的一样,但是要使用他就需要先建立连接! 远程库有两种,一个是自己搭建的git服务器:另一种就是使用GitHub,这个网站就是提供 ...
- Windows下.svn文件夹的最简易删除方法(附linux)
如果想删除Windows下的.svn文件夹,通过手动删除的渠道是最麻烦的,因为每个文件夹下面都存在这样的文件.下面是一个好办法:建立一个文本文件,取名为kill-svn-folders.reg(扩展名 ...
- java 多线程系列---JUC原子类(五)之AtomicLongFieldUpdater原子类
AtomicLongFieldUpdater介绍和函数列表 AtomicLongFieldUpdater可以对指定"类的 'volatile long'类型的成员"进行原子更新.它 ...
- 问题:C#将base64转换成二进制图片;结果:c# Base64编码和图片的互相转换代码
c# Base64编码和图片的互相转换代码 Base64编码在Web方面有很多应用,譬如在URL.电子邮件方面.网上有很多相关的资源用于提供Base64编码和其他编码的转换,.Net Framewor ...
- DAY4-函数进阶
目录: 一.迭代器 二.生成器 三.面向过程编程 四.三元表达式.列表推导式.生成器表达式 五.第归与二分法 六.匿名函数 七.内置函数 练习 一.迭代器 一.迭代的概念 #迭代器即迭代的工具,那什么 ...
- buntu下shell脚本运行异常:bash和…
转载于:http://www.51testing.com/?uid-225738-action-viewspace-itemid-208702 我用bash到语法写了一个shell脚本(准确的说是把书 ...