bzoj4617: [Wf2016]Spin Doctor
Description
Input
Output
求出c=1的点的凸包,选出的S,T会使答案为一对包含了凸包的平行线间(含线上)的最小点数
当凸包只有一点时,若这个点不和其余c=1的点重合则答案为1,否则最坏情况下所有与凸包重合的点都被记入答案
当凸包上只有两点时,凸包为一条线段,线段上点数为所求
否则让平行线绕凸包类似旋转卡壳地扫描180度,对每个c=0的点,二分求出这个点进入和离开平行线时平行线对应的角度,得到每个点的出现区间,可以排序计算答案
#include<cstdio>
#include<algorithm>
#include<cmath>
char buf[],*ptr=buf-;
typedef long double ld;
typedef long long i64;
int _(){
int x=,f=,c=*++ptr;
while(c<)c=*++ptr;
while(c>)x=x*+c-,c=*++ptr;
return x*f;
}
int abs(int x){return x>?x:-x;}
struct pos{
int x,y;
int abs(){return (x>?x:-x)+(y>?y:-y);}
void fix(){if(y<||y==&&x<)x=-x,y=-y;}
}ps1[],ps2[],ps[];
bool operator<(pos a,pos b){return a.y!=b.y?a.y<b.y:a.x<b.x;}
bool operator==(pos a,pos b){return a.x==b.x&&a.y==b.y;}
pos operator+(pos a,pos b){return (pos){a.x+b.x,a.y+b.y};}
pos operator-(pos a,pos b){return (pos){a.x-b.x,a.y-b.y};}
i64 operator*(pos a,pos b){return i64(a.x)*b.y-i64(a.y)*b.x;}
i64 dot(pos a,pos b){return i64(a.x)*b.x+i64(a.y)*b.y;}
bool cmp(pos a,pos b){
i64 x=a*b;
return x?x>:a.abs()<b.abs();
}
int p1=,p2=,pp=,n,ans=;
ld as[];
const ld pi=.1415926535897932384626433832795l,_2pi=pi*;
void fix(ld&x,ld m){
while(x>=m)x-=m;
while(x<)x+=m;
}
struct ev{
pos a;
int t;
}es[];
bool operator<(ev a,ev b){
return a.a*b.a>;
}
int s0=,ep=;
int main(){
fread(buf,,sizeof(buf),stdin);
n=_();
for(int i=,x,y,c;i<n;++i){
x=_();y=_();c=_();
if(c)ps1[p1++]=(pos){x,y};
else ps2[p2++]=(pos){x,y};
}
int _p1=p1;
ans=p1;
std::sort(ps1,ps1+p1);
p1=std::unique(ps1,ps1+p1)-ps1;
std::sort(ps2,ps2+p2);
pos p0=ps1[];
for(int i=;i<p1;++i)ps1[i]=ps1[i]-p0;
std::sort(ps1+,ps1+p1,cmp);
ps[pp++]=(pos){,};
for(int i=;i<p1;++i){
while(pp>=&&(ps[pp-]-ps[pp-])*(ps1[i]-ps[pp-])>=)--pp;
ps[pp++]=ps1[i];
}
for(int i=;i<pp;++i)ps[i]=ps[i]+p0;
if(pp==){
if(_p1>)for(int i=;i<p2;++i)if(ps2[i]==ps[])++ans;
return printf("%d",ans),;
}
if(pp==){
for(int i=;i<p2;++i)if((ps2[i]-ps[])*(ps2[i]-ps[])==&&dot(ps2[i]-ps[],ps2[i]-ps[])<=)++ans;
return printf("%d",ans),;
}
ld xs=,ys=,a0;
for(int i=;i<pp;++i)xs+=ps[i].x,ys+=ps[i].y,ps[pp+i]=ps[i];
xs/=pp,ys/=pp;
ps[pp*]=ps[];
ps[pp*+]=ps[];
for(int i=;i<pp;++i)as[i]=std::atan2(ps[i].y-ys,ps[i].x-xs);
a0=as[];
for(int i=;i<pp;++i)fix(as[i]-=a0,_2pi);
for(int i=;i<p2;++i){
pos w=ps2[i];
ld a=std::atan2(w.y-ys,w.x-xs);
fix(a-=a0,_2pi);
int p=std::upper_bound(as,as+pp,a)-as;
if((ps[p-]-w)*(ps[p]-w)>=){
++ans;
continue;
}
ld b=a+pi;
fix(b,_2pi);
int p2=std::upper_bound(as,as+pp,b)-as;
int L=p,R=p2-,M;
if(L>R)R+=pp;
while(L<R){
M=L+R>>;
if((ps[M+]-w)*(ps[M]-w)>)L=M+;
else R=M;
}
pos _l=ps[L]-w;
_l.fix();
L=p2;R=p-;
if(L>R)R+=pp;
while(L<R){
M=L+R>>;
if((ps[M+]-w)*(ps[M]-w)<)L=M+;
else R=M;
}
pos _r=ps[L]-w;
_r.fix();
es[ep++]=(ev){_l,},es[ep++]=(ev){_r,-};
if(_l*_r<)++s0;
}
std::sort(es,es+ep);
int s1=s0;
for(int i=,j=;i<ep;){
for(;j<ep&&es[i].a*es[j].a==;++j);
for(;i<j;++i)s0+=es[i].t;
if(s0<s1)s1=s0;
}
printf("%d",ans+s1);
return ;
}
bzoj4617: [Wf2016]Spin Doctor的更多相关文章
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- TAE words all
// vol 1 could do with sth rhinoplasty angst the wee small hours familial Munich gladi ...
- spin.js
$ajax提交,菊花加载的方式和位置: $.ajax({ type: "get", url: "http://www.xxx.com/test.html", b ...
- ros::spin() 和 ros::spinOnce() 区别及详解
版权声明:本文为博主原创文章,转载请标明出处: http://www.cnblogs.com/liu-fa/p/5925381.html 博主提示:本文基于ROS Kinetic Kame,如有更(g ...
- 为大家分享一个 Ajax Loading —— spin.js
我们在做Ajax 异步请求的时候,一般都会利用一个动态的 Gif 小图片来制作一个Ajax Loading ,以便增加用户体验. 今天在网上发现了一个 Spin.js ,该 js 脚本压缩后5k,可以 ...
- CF 84D Doctor(二分)
题目链接: 传送门 Doctor time limit per test:1 second memory limit per test:256 megabytes Description Th ...
- [杂谈] There is a Doctor in My Computer.
(p.s. 附带手写翻译,有错轻喷) Admin: Hi. (嗨) Doctor: How do you do? What brings you to see me? ...
- InnoDB Spin rounds per wait在>32位机器上可能为负
今天发现一个系统innodb的spin rounds per wait为负,感觉很奇怪,原来是个bug: For example (output from PS but we have no patc ...
- InnoDB Status Output – Buffer Pool and Spin Rounds
InnoDB has a good source of information about its status which can be requested every time you need ...
随机推荐
- Android 之 Activity的生命周期
- SSM框架学习之高并发秒杀业务--笔记1-- 项目的创建和依赖
在慕课网上看了Java高并发秒杀API视屏后,觉得这个案例真的让我学到了很多,现在重新自己实现一遍,博客记下,顺便分析其中的要点. 第一步是项目的创建和依赖 利用Maven去创建工程然后导入Idea中 ...
- hdu 4635 Strongly connected
http://acm.hdu.edu.cn/showproblem.php?pid=4635 我们把缩点后的新图(实际编码中可以不建新图 只是为了概念上好理解)中的每一个点都赋一个值 表示是由多少个点 ...
- UINavigationController导航控制器
UINavigationController导航控制器,是多个界面间跳转的重要元素,可以理解为它存储着多个viewController,它的存储结构是栈,栈的特点是先进后出,所以添加视图控制器时,要特 ...
- MongoDB下载文件 百度盘共享
1> mongodb下载地址: http://www.mongodb.org/downloads 官方下载不了,可以到百度共享盘里面下载 MongoDB 2.6.5 Windows 64位: ...
- linux C++ 共享库导出类
1.共享库的对外接口函数的声明必须加上extern “C”. 2.使用共享库对话接口函数生成的对象指针时在该对象未被释放之前不能关闭共享库句柄,否则会出现segmentation fault错误. 以 ...
- 软件测试面试(2)LR篇
一:LoadRunner常见问题整理 1.LR 脚本为空的解决方法: 1.去掉ie设置中的第三方支持取消掉 2.在系统属性-高级-性能-数据执行保护中,添加loadrunner安装目录中的vugen. ...
- layoutSubviews总结
ios layout机制相关方法 - (CGSize)sizeThatFits:(CGSize)size - (void)sizeToFit ——————- - (void)layoutSubview ...
- 后台返回JSON关于日期的格式化
JSONObject 可以将java对象转换成json格式,用于处理ajax请求或者做app是与前台的交互. 但是Date类型的也会做转换,很多时候我们是不想将日期的年月日分别转换成json的.可以通 ...
- Fragment的初步设计
Fragment的初步设计 Fragment功能 Fragment将每一段碎片时间归类到一个具体的事件上: 使用者可以创建多个事件对碎片时间进行分类: 使用者点击事件会进入用户自己设置好的事件对应的A ...