BZOJ2934 : [Poi1999]祭坛问题
对于每个祭坛,算出每条线段阻碍它的角度区间,然后排序求并看看是否有空位即可,时间复杂度$O(n^2\log n)$。
这题在Main上官方时限是0.2S,因此需要几个常数优化:
$1.$为了避免用atan2(y,x)算角度,改成算斜率,所以需要分$4$个方向讨论。
$2.$对区间排序时,不要直接对结构体排序,而是对其指针排序。
$3.$在计算某个祭坛时,除了它本身需要特别计算之外,其它祭坛可以直接看成没有缺口的矩形,可以减少$n$个事件。
$4.$在计算的过程中,不断收缩左右边界,当左右边界重合时即可直接判定为不可能。
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1005,BUF=50000;
const double eps=1e-9,inf=1e9;
int n,m,cnt,i,X,k,ce,flag;char dir[N],Buf[BUF],*buf=Buf;double L,R;
inline void read(int&a){for(a=0;*buf<48;buf++);while(*buf>47)a=a*10+*buf++-48;}
inline void read(char&a){while(*buf<'A')buf++;a=*buf++;}
struct P{int x,y;P(){}P(int _x,int _y){x=_x,y=_y;}}a[N];
struct seg{
P x,y;
seg(){}
seg(P _x,P _y){
x=_x,y=_y;
if(x.x>y.x||x.y>y.y)swap(x,y);
}
}b[N*5],c[N*4],f[N];
struct E{
double l,r;
void set(double _l,double _r){
l=_l,r=_r;
if(l<L+eps)L=max(L,r);
if(r>R-eps)R=min(R,l);
if(L+eps>R)k=1;
}
}e[N*4],*q[N*4];
inline bool cmp(E*x,E*y){return x->l<y->l;}
inline bool cal(int x,int y,double&t){
if(x<=0)return 0;
t=1.0*y/x;
return 1;
}
inline double fix(double x){return x>0?inf:-inf;}
void initS(int x,int y){
cal(-f[X].x.y+y,f[X].x.x-x,L);
cal(-f[X].y.y+y,f[X].y.x-x,R);
if(L>R)swap(L,R);
for(int i=1;i<=m;i++)if((i+4)/5==X){
seg&j=b[i];double l,r;
if(!cal(-j.x.y+y,j.x.x-x,l))continue;
if(!cal(-j.y.y+y,j.y.x-x,r))r=fix(l);
if(l>r)swap(l,r);
if(r<L-eps||l>R+eps)continue;
e[ce++].set(l,r);
}
for(int i=1;i<=cnt&&!k;i++)if((i+3)/4!=X){
seg&j=c[i];double l,r;
if(!cal(-j.x.y+y,j.x.x-x,l))continue;
if(!cal(-j.y.y+y,j.y.x-x,r))r=fix(l);
if(l>r)swap(l,r);
if(r<L-eps||l>R+eps)continue;
e[ce++].set(l,r);
}
}
void initN(int x,int y){
cal(f[X].y.y-y,f[X].y.x-x,L);
cal(f[X].x.y-y,f[X].x.x-x,R);
if(L>R)swap(L,R);
for(int i=1;i<=m;i++)if((i+4)/5==X){
seg&j=b[i];double l,r;
if(!cal(j.y.y-y,j.y.x-x,r))continue;
if(!cal(j.x.y-y,j.x.x-x,l))l=fix(r);
if(l>r)swap(l,r);
if(r<L-eps||l>R+eps)continue;
e[ce++].set(l,r);
}
for(int i=1;i<=cnt&&!k;i++)if((i+3)/4!=X){
seg&j=c[i];double l,r;
if(!cal(j.y.y-y,j.y.x-x,r))continue;
if(!cal(j.x.y-y,j.x.x-x,l))l=fix(r);
if(l>r)swap(l,r);
if(r<L-eps||l>R+eps)continue;
e[ce++].set(l,r);
}
}
void initW(int x,int y){
cal(-f[X].x.x+x,f[X].x.y-y,L);
cal(-f[X].y.x+x,f[X].y.y-y,R);
if(L>R)swap(L,R);
for(int i=1;i<=m;i++)if((i+4)/5==X){
seg&j=b[i];double l,r;
if(!cal(-j.x.x+x,j.x.y-y,l))continue;
if(!cal(-j.y.x+x,j.y.y-y,r))r=fix(l);
if(l>r)swap(l,r);
if(r<L-eps||l>R+eps)continue;
e[ce++].set(l,r);
}
for(int i=1;i<=cnt&&!k;i++)if((i+3)/4!=X){
seg&j=c[i];double l,r;
if(!cal(-j.x.x+x,j.x.y-y,l))continue;
if(!cal(-j.y.x+x,j.y.y-y,r))r=fix(l);
if(l>r)swap(l,r);
if(r<L-eps||l>R+eps)continue;
e[ce++].set(l,r);
}
}
void initE(int x,int y){
cal(f[X].y.x-x,f[X].y.y-y,L);
cal(f[X].x.x-x,f[X].x.y-y,R);
if(L>R)swap(L,R);
for(int i=1;i<=m;i++)if((i+4)/5==X){
seg&j=b[i];double l,r;
if(!cal(j.y.x-x,j.y.y-y,r))continue;
if(!cal(j.x.x-x,j.x.y-y,l))l=fix(r);
if(l>r)swap(l,r);
if(r<L-eps||l>R+eps)continue;
e[ce++].set(l,r);
}
for(int i=1;i<=cnt&&!k;i++)if((i+3)/4!=X){
seg&j=c[i];double l,r;
if(!cal(j.y.x-x,j.y.y-y,r))continue;
if(!cal(j.x.x-x,j.x.y-y,l))l=fix(r);
if(l>r)swap(l,r);
if(r<L-eps||l>R+eps)continue;
e[ce++].set(l,r);
}
}
bool check(){
if(k)return 0;
for(int i=0;i<ce;i++)q[i]=e+i;
sort(q,q+ce,cmp);
for(int i=0;i<ce;i++){
if(q[i]->l>L+eps)return 1;
if(L<q[i]->r)L=q[i]->r;
}
return 0;
}
int main(){
fread(Buf,1,BUF,stdin);read(n);
for(i=1;i<=n;i++){
int x1,y1,x2,y2,o;char d;
read(x1),read(y1),read(x2),read(y2),read(d);
x1<<=2,y1<<=2,x2<<=2,y2<<=2;
if(x1>x2)swap(x1,x2);
if(y1>y2)swap(y1,y2);
a[i]=P((x1+x2)/2,(y1+y2)/2);
dir[i]=d;
if(d!='S')b[++m]=seg(P(x1,y1),P(x2,y1));
else{
o=(x1+x2)/2;
b[++m]=seg(P(x1,y1),P((x1+o)/2,y1));
b[++m]=seg(P(x2,y1),P((x2+o)/2,y1));
f[i]=seg(P((x1+o)/2,y1),P((x2+o)/2,y1));
}
if(d!='N')b[++m]=seg(P(x1,y2),P(x2,y2));
else{
o=(x1+x2)/2;
b[++m]=seg(P(x1,y2),P((x1+o)/2,y2));
b[++m]=seg(P(x2,y2),P((x2+o)/2,y2));
f[i]=seg(P((x1+o)/2,y2),P((x2+o)/2,y2));
}
if(d!='W')b[++m]=seg(P(x1,y1),P(x1,y2));
else{
o=(y1+y2)/2;
b[++m]=seg(P(x1,y1),P(x1,(y1+o)/2));
b[++m]=seg(P(x1,y2),P(x1,(y2+o)/2));
f[i]=seg(P(x1,(y1+o)/2),P(x1,(y2+o)/2));
}
if(d!='E')b[++m]=seg(P(x2,y1),P(x2,y2));
else{
o=(y1+y2)/2;
b[++m]=seg(P(x2,y1),P(x2,(y1+o)/2));
b[++m]=seg(P(x2,y2),P(x2,(y2+o)/2));
f[i]=seg(P(x2,(y1+o)/2),P(x2,(y2+o)/2));
}
c[++cnt]=seg(P(x1,y1),P(x2,y1));
c[++cnt]=seg(P(x1,y2),P(x2,y2));
c[++cnt]=seg(P(x1,y1),P(x1,y2));
c[++cnt]=seg(P(x2,y1),P(x2,y2));
}
for(X=1;X<=n;X++){
ce=k=0;
if(dir[X]=='S')initS(a[X].x,a[X].y);
if(dir[X]=='N')initN(a[X].x,a[X].y);
if(dir[X]=='W')initW(a[X].x,a[X].y);
if(dir[X]=='E')initE(a[X].x,a[X].y);
if(check())flag=1,printf("%d\n",X);
}
if(!flag)puts("BRAK");
return 0;
}
BZOJ2934 : [Poi1999]祭坛问题的更多相关文章
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- BZOJ 2933([Poi1999]地图-区间Dp)
2933: [Poi1999]地图 Time Limit: 1 Sec Memory Limit: 128 MB Submit: 7 Solved: 7 [ Submit][ Status] ...
- 2929: [Poi1999]洞穴攀行
2929: [Poi1999]洞穴攀行 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 80 Solved: 41[Submit][Status][Di ...
- BZOJ 2929: [Poi1999]洞穴攀行
2929: [Poi1999]洞穴攀行 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 351 Solved: 195[Submit][Status][ ...
- BZOJ2935: [Poi1999]原始生物(欧拉回路)
2935: [Poi1999]原始生物 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 150 Solved: 71[Submit][Status][D ...
- bzoj 2929 [Poi1999]洞穴攀行 网络流
2929: [Poi1999]洞穴攀行 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 499 Solved: 295[Submit][Status][ ...
- BZOJ2936 Codevs3634 POI1999 积水 【并查集】*
BZOJ2936 Codevs3634 POI1999 积水 题目描述 有这样一块土地,它可以被划分成N×M个正方形小块,每块面积是一平方英寸,第i行第j列的小块可以表示成P(i,j).这块土地高低不 ...
- 【BZOJ2927】[Poi1999]多边形之战 博弈
[BZOJ2927][Poi1999]多边形之战 Description 多边形之战是一个双人游戏.游戏在一个有n个顶点的凸多边形上进行,这个凸多边形的n-3条对角线将多边形分成n-2个三角形,这n- ...
- luoguP3415 祭坛
https://www.luogu.org/problemnew/show/P3415 考虑二分结界层数,将 n 个点按 x 大小依次加入答案,一行一行的做,用树状数组维护当前这一行中[0, x - ...
随机推荐
- 解决VS2010 C++ DLL不能断点调试的问题
问题产生的过程是这样的,向exe项目(CSharp)中添加dll工程(c++开发)的引用,并将引用工程的属性“Link Library Dependencies”的值设为true,这样,在不加入lib ...
- Swift - 懒加载(lazy initialization)
Swift中是存在和OC一样的懒加载机制的,在程序设计中,我们经常会使用 懒加载 ,顾名思义,就是用到的时候再开辟空间 懒加载 格式: lazy var 变量: 类型 = { 创建变量代码 }() 懒 ...
- sqlserver 用户、账号、安全等问题小汇
一.孤立账号 SQL Server 的用户安全管理分两层,整个SQL Server 服务器一层,每个数据库一层. 在服务器层的帐号,叫登录账户(SQL Server:服务器角色),可以设置它管理整个S ...
- cutpFTP设置步骤
cutpFTP设置步骤 平常时为了方便两台电脑之间传送数据,我们可以使用cutpftp这个工具实现,而且cutpftp还具有定时传送的功能,非常方便使用.以下是使用该工具的“同步文件夹”功能同步两台电 ...
- C# 使用Conditional特性而不是#if条件编译
概述 #if/#endif 语句常用来基于同一份源码生成不同的编译结果,其中最常见的就是debug版和release版.但是这些工具在实际应用中并不是非常友好,因为它们容易被滥用,其代码页进而难以理解 ...
- 同一服务器配置DataGuard
实验环境:1.虚拟机VMware Server 1.0.62.操作系统:ora10g@linux5 /home/oracle$ cat /etc/redhat-releaseRed Hat Enter ...
- CXF学习(3) wsdl文件
<!--一次webservice调用,其实并不是方法调用,而是发送SOAP消息 ,即xml片段--> <!--以上一篇中的wsdl文档为例,这里我将注释写到文档中 --> &l ...
- C#动态方法调用
此篇将介绍C#如何在运行时动态调用方法.当某些类型是运行时动态确定时,编译时的静态编码是无法解决这些动态对象或类的方法调用的.此篇则给你一把利剑,让动态对象的方法调用成为可能. 1.动态调用dll里的 ...
- LIS的nlogn
nlogn老忘,开个帖记录一下 开一个栈,每次取栈顶元素top和读到的元素temp做比较,如果temp > top 则将temp入栈:如果temp < top则二分查找栈中的比temp大的 ...
- [Linux][VMWare] 学习笔记之安装Linux系统-网络配置
最近开始折腾Linux,在本机装了个VMWare和Centos,装完之后虚拟机里面的OS可以上网,但是使用SecureCRT连接不上虚拟机,开始折腾这个网络. vmware安装好以后,会自动添加两张网 ...