BZOJ2640 : 可见区域
设$base$表示直接能看到的面积,$f[i]$表示仅去掉线段$i$后新增的面积,$g[i][j]$表示仅去掉线段$i$和$j$后新增的面积。
删除一条线段的答案为$base+\max(f[i])$。
删除两条线段的答案为$base+\max(g[i][j]+f[i]+f[j],f最大值+f次大值)$。
转一圈扫描线,按照到原点从近到远用set维护所有存在的线段。
对于相邻两条扫描线中间的部分,找到最近的三条线段$A,B,C$,求出到原点的三角形面积$SA,SB,SC$,则$SA$贡献给$base$,$SB-SA$贡献给$f[A]$,$SC-SB$贡献给$g[A][B]$。
由此可以发现$g$中只有$O(n)$项非$0$,可以暴力枚举。
时间复杂度$O(n\log n)$。
#include<cstdio>
#include<algorithm>
#include<set>
#include<map>
using namespace std;
const int N=100010;
inline int sgn(int x){
if(x>0)return 1;
if(x<0)return -1;
return 0;
}
int n,ce,i,j,cg;bool in[N];
struct P{
int x,y;
P(){}
P(int _x,int _y){x=_x,y=_y;}
int pos()const{return x?x<0:y<0;}
P operator-(const P&b)const{return P(x-b.x,y-b.y);}
void read(){scanf("%d%d",&x,&y);}
}a[N][2],A,B,X,PRE;
struct PD{
double x,y;
PD(){}
PD(double _x,double _y){x=_x,y=_y;}
double len(){return x*x+y*y;}
};
struct E{
P o;int t;
E(){}
E(P _o,int _t){o=_o,t=_t;}
}e[N];
struct Num{
double x;bool inf;
Num(){x=0,inf=0;}
Num(double _x,bool _inf){x=_x,inf=_inf;}
void up(const Num&b){
if(inf)return;
if(b.inf){inf=1;return;}
if(x<b.x)x=b.x;
}
void operator+=(const Num&b){x+=b.x,inf|=b.inf;}
Num operator+(const Num&b)const{return Num(x+b.x,inf|b.inf);}
void write(){if(inf)puts("infinite");else printf("%.2f\n",x/2);}
bool operator<(const Num&b)const{
if(inf!=b.inf)return inf<b.inf;
return x<b.x;
}
}f[N],base,ans,tmp;
typedef pair<int,int>PI;
typedef pair<PI,Num>PIN;
PIN g[N];
inline int cross(const P&a,const P&b){return a.x*b.y-a.y*b.x;}
inline int cmpp(const P&a,const P&b){
if(a.pos()!=b.pos())return a.pos()-b.pos();
return sgn(cross(a,b));
}
inline bool cmpe(const E&a,const E&b){return cmpp(a.o,b.o)<0;}
inline bool has_intersection(const P&a,const P&b,const P&p,const P&q){
int d1=sgn(cross(b-a,p-a)),d2=sgn(cross(b-a,q-a));
int d3=sgn(cross(q-p,a-p)),d4=sgn(cross(q-p,b-p));
if(d1*d2<0&&d3*d4<0)return 1;
return 0;
}
inline PD line_intersection(const P&a,const P&b,const P&p,const P&q){
int U=cross(p-a,q-p),D=cross(b-a,q-p);
double o=1.0*U/D;
return PD(a.x+(b.x-a.x)*o,a.y+(b.y-a.y)*o);
}
inline double area(const PD&a,const PD&b){return -a.x*b.y+a.y*b.x;}
struct cmp{
bool operator()(int x,int y){
double dx=line_intersection(A,X,a[x][0],a[x][1]).len(),
dy=line_intersection(A,X,a[y][0],a[y][1]).len();
return dx<dy;
}
};
set<int,cmp>T;
inline void change(int x){
if(!in[x])T.insert(x);else T.erase(x);
in[x]^=1;
}
inline void solve(){
if(!cmpp(PRE,X))return;
set<int,cmp>::iterator it=T.begin();
static int id[3];
static Num v[3];
int i,o,x,y;
for(i=0;i<3;i++)id[i]=0;
for(i=0;i<3;i++){
if(it==T.end())break;
id[i]=*it;
it++;
}
for(i=0;i<3;i++)if(!id[i])v[i]=Num(0,1);else{
o=id[i];
v[i]=Num(area(line_intersection(A,PRE,a[o][0],a[o][1]),line_intersection(A,X,a[o][0],a[o][1])),0);
}
for(i=2;i;i--)if(!v[i].inf)v[i].x-=v[i-1].x;
base+=v[0];
if(id[0])f[id[0]]+=v[1];
if(id[0]&&id[1]){
x=id[0],y=id[1];
if(x>y)swap(x,y);
g[++cg]=PIN(PI(x,y),v[2]);
}
}
int main(){
scanf("%d",&n);
A=P(0,0);
PRE=X=B=P(0,2000);
for(i=1;i<=n;i++){
a[i][0].read(),a[i][1].read();
if(a[i][0].x>a[i][1].x)swap(a[i][0],a[i][1]);
if(has_intersection(A,B,a[i][0],a[i][1])||a[i][0].x<0&&a[i][1].x==0&&a[i][1].y>0)change(i);
e[++ce]=E(a[i][0],i);
e[++ce]=E(a[i][1],i);
}
sort(e+1,e+ce+1,cmpe);
for(i=1;i<=ce;i++){
X=e[i].o;
solve();
change(e[i].t);
PRE=X;
}
X=B;
solve();
base.write();
ans=Num(0,0);
for(i=1;i<=n;i++)ans.up(f[i]);
ans+=base;
ans.write();
ans=Num(0,0);
sort(g+1,g+cg+1);
for(i=1;i<=cg;i=j){
tmp=f[g[i].first.first]+f[g[i].first.second];
for(j=i;j<=cg&&g[i].first==g[j].first;j++)tmp+=g[j].second;
ans.up(tmp);
}
sort(f+1,f+n+1);
ans.up(f[n]);
if(n>1)ans.up(f[n]+f[n-1]);
ans+=base;
ans.write();
return 0;
}
BZOJ2640 : 可见区域的更多相关文章
- .Net Core MVC 网站开发(Ninesky) 2.2、栏目管理功能-System区域添加
在asp或asp.net中为了方便网站的结构清晰,通常把具有类似功能的页面放到一个文件夹中,用户管理功能都放在Admin文件夹下,用户功能都放在Member文件夹下,在MVC中,通常使用区域(Area ...
- MMORPG大型游戏设计与开发(攻击区域 扇形)
距离上次发布已经有了很长一段时间,期间由于各种原因没有更新这方面的技术分享,在这里深表遗憾.在MMO或其他的游戏中,会有针对各种形状的计算,通常在攻击区域里不会很复杂,常见的为矩形.圆形.扇形.今天分 ...
- MUI开发APP,scroll组件,运用到区域滚动
最近在开发APP的过程中,遇到一个问题,就是内容有一个固定的头部和底部. 头部就是我们常用的header了,底部的话,就放置一个button,用来提交页面数据或者进入下一个页面等,效果 ...
- [Tool] 插入折叠区域功能
之前写了一个 仿博客园网页端推荐的插入代码插件, 后来在总结一些技术文档时,总是想把一些属性或者方法,参数等,都用表格的形式清晰的列举出来,但是插入的表格太大的话,上下跨度就显得特别大,来回上下滚动的 ...
- 【无私分享:ASP.NET CORE 项目实战(第九章)】创建区域Areas,添加TagHelper
目录索引 [无私分享:ASP.NET CORE 项目实战]目录索引 简介 在Asp.net Core VS2015中,我们发现还有很多不太简便的地方,比如右击添加视图,转到试图页等功能图不见了,虽然我 ...
- FFmpeg滤镜实现区域视频增强 及 D3D实现视频播放区的拉大缩小
1.区域视频增强 FFmpeg滤镜功能十分强大,用滤镜可以实现视频的区域增强功能. 用eq滤镜就可以实现亮度.对比度.饱和度等的常用视频增强功能. 推荐两篇写得不错的博文: (1)ffmpeg综合应用 ...
- Java 内存区域与内存溢出
内存区域 Java 虚拟机在执行 Java 程序的过程中会把他所管理的内存划分为若干个不同的数据区域.Java 虚拟机规范将 JVM 所管理的内存分为以下几个运行时数据区:程序计数器.Java 虚拟机 ...
- jvm内存区域
概述 jvm内存分为几个区域: 程序计数器 虚拟机栈 本地方法栈 堆 方法区 运行时常量池 直接内存 这些内存区域是在java进程中细分的,为java程序提供服务 不同的区域存储的内容不一样,生命周期 ...
- ps如何裁剪掉图片的不规则区域
按P,鼠标变成钢笔工具,点选住待清除区域,如下: 按ctrl+enter, 将点线变成选中区域: 按delete删除: ctrl+D取消选中区域 完成!
随机推荐
- Arduino语法-变量和常量
变量的声明: int led=11 一般变量的声明方法为类型名+变量名+变量初始化值.变量名的写法约定为首字母小写 变量的作用范围又称为作用域,变量的作用范围与该变量在哪儿声明有关,大致分为如下两种: ...
- poj2689 Prime Distance题解报告
题目戳这里 [题目大意] 给定一个区间[L,R],求区间内的质数相邻两个距离最大和最小的. [思路分析] 其实很简单呀,很明显可以看出来是数论题,有关于质数的知识. 要注意一下的就是L和R的数据范围都 ...
- C#调用Bartender打印
BarTender是一款优秀的条形码打印软件,可以支持很多种类型的条形码设计和打印,具体大家可参考他的官网(http://www.seagullscientific.com/aspx/products ...
- Scrapy+Scrapy-redis+Scrapyd+Gerapy 分布式爬虫框架整合
简介:给正在学习的小伙伴们分享一下自己的感悟,如有理解不正确的地方,望指出,感谢~ 首先介绍一下这个标题吧~ 1. Scrapy:是一个基于Twisted的异步IO框架,有了这个框架,我们就不需要等待 ...
- 2018-2019-2 网络对抗技术 20165325 Exp1 PC平台逆向破解
2018-2019-2 网络对抗技术 20165325 Exp1 PC平台逆向破解(BOF实验) 实验有三个模块: (一)直接修改程序机器指令,改变程序执行流程: (二)通过构造输入参数,造成BOF攻 ...
- 2018-2019-2 20175204 张湲祯 实验二《Java面向对象程序设计》实验报告
2018-2019-2-20175204 张湲祯 实验二 <Java开发环境的熟悉>实验报告 实验二 Java面向对象程序设计 一.实验内容: 初步掌握单元测试和TDD 理解并掌握面向对象 ...
- CentOs7.5安装Redis
前言 虽说现在都是买服务了,可是自己做的小DEMO偶尔也用用Redis,不会装也不行 变更记录 # 19.4.24 起笔 正文 官网 https://redis.io/ 首先去官网找到最新的链接 截 ...
- router-link 返回上页 和 新窗口打开链接
1.如果使用了Vue-router的话,就可以用 this.$router.go(-1) 实现返回: 2.如果没使用vue-router,就可以用 window.history.go(-1) 实现返回 ...
- 跨域资源共享(CORS)
同源策略 同源策略是浏览器的一个安全策略,只允许当前页面或当前域下发送请求,如果向其他域发送请求,会被浏览器拦截 同源的意思:协议.IP地址.端口三者一致,浏览器才会认为是同一个域,三者中有一个不一致 ...
- shell 重定向 2>&1 2>/dev/null 理解笔记
// 函数 输入输出重定向 1.函数 function hello(){ echo '1111' } ------- hello hello(){ // function 可以省略 echo '222 ...