BZOJ 4814 Luogu P3699 [CQOI2017]小Q的草稿 (计算几何、扫描线、set)
题目链接
(BZOJ) http://lydsy.com/JudgeOnline/problem.php?id=4814
(Luogu) https://www.luogu.org/problem/P3699
题解
写了这么多扫描线依然不会写。。
首先思路非常简单,枚举每个点,把所有的直线按照极角序排序,然后扫描线解决。(注意这里扫描线是一条从这个点出发的射线)
事件有三种: (1)插入一条线段。(2)删除一条线段。(3)查询某个位置与该点的连线是否被某一目前存在的直线穿过。
显然可以用一个set维护直线,set的比较函数定义为比较这个点与当前射线的交点和当前枚举点的距离。
细节处理: (1)对于一个三角形只有与当前枚举点的线段夹角最大的两个点之间的连边有用。(2)如果遇到跨过极角序分界点(\(-\pi\)或\(\pi\)),显然可以拆成两条线段。
精度问题:由于set判相等会有精度误差,因此尽量不用find(), 可以记下来每条直线插入到set中的位置。另外除了求交点距离之外的部分全都可以不用double实现。
常数问题: 注意一定不能在排序比较函数里调用三角函数!血淋淋的教训……
时间复杂度\(O(n^2\log n)\).
代码
#include<bits/stdc++.h>
#define llong long long
using namespace std;
inline int read()
{
int x=0; bool f=1; int c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
for(; isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+(c^'0');
if(f) return x;
return -x;
}
const int N = 1000;
const double PI = acos(-1);
const double EPS = 1e-8;
inline int dcmp(double x) {return x<-EPS?-1:(x>EPS?1:0);}
struct Point
{
llong x,y;
Point() {}
Point(llong _x,llong _y) {x = _x,y = _y;}
inline double ang() const {return atan2(y,x);}
};
typedef Point Vector;
inline Point operator +(const Point &x,const Point &y) {return Point(x.x+y.x,x.y+y.y);}
inline Point operator -(const Point &x,const Point &y) {return Point(x.x-y.x,x.y-y.y);}
inline llong Dot(const Point &x,const Point &y) {return x.x*y.x+x.y*y.y;}
inline llong Cross(const Point &x,const Point &y) {return x.x*y.y-x.y*y.x;}
inline llong EuclidDist2(const Point &x,const Point &y) {return (x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y);}
inline bool operator <(const Point &x,const Point &y) {return Cross(x,y)>0;}
struct Line
{
Point x,y;
Line() {}
Line(const Point &_x,const Point &_y) {x = _x,y = _y;}
};
struct Triangle
{
Point a[3];
};
struct Query
{
int opt,id; Point x; double ang;
} qr[N*5+3];
Triangle b[N+3];
Point a[N+3];
Line stk[N+3];
int n,m,q;
Vector l;
inline bool cmp_qr(const Query &x,const Query &y) {int flg = dcmp(x.ang-y.ang); return flg<0 || (flg==0 && x.opt<y.opt);}
inline double calcdis(const Line &x)
{
double t = (double)Cross(l,x.x)/((double)Cross(x.y-x.x,l));
double rx = x.x.x+(x.y.x-x.x.x)*t,ry = x.x.y+(x.y.y-x.x.y)*t;
return rx*rx+ry*ry;
}
struct Element
{
Line x;
Element() {}
Element(Line _x) {x = _x;}
inline bool operator <(const Element &arg) const
{
double dis1 = calcdis(x),dis2 = calcdis(arg.x);
return dcmp(dis1-dis2)<0;
}
};
multiset<Element> s;
multiset<Element>::iterator adr[N+3];
int main()
{
scanf("%d%d",&n,&m);int ans = 0;
for(int i=1; i<=n; i++) scanf("%lld%lld",&a[i].x,&a[i].y);
for(int i=1; i<=m; i++) scanf("%lld%lld%lld%lld%lld%lld",&b[i].a[0].x,&b[i].a[0].y,&b[i].a[1].x,&b[i].a[1].y,&b[i].a[2].x,&b[i].a[2].y);
for(int i=1; i<=n; i++)
{
q = 0; l = Vector(-1,0); Line cur;
for(int j=1; j<=m; j++)
{
Point t[3];
for(int k=0; k<3; k++) t[k] = b[j].a[k]-a[i];
sort(t,t+3),stk[j].x = t[0],stk[j].y = t[2];
if(stk[j].x.y>=0 && stk[j].y.y<=0)
{
adr[j] = s.insert(Element(stk[j]));
q++; qr[q].x = stk[j].y; qr[q].id = j; qr[q].opt = 3;
q++; qr[q].x = stk[j].x; qr[q].id = j; qr[q].opt = 1;
}
else
{
q++; qr[q].x = stk[j].x; qr[q].id = j; qr[q].opt = 1;
q++; qr[q].x = stk[j].y; qr[q].id = j; qr[q].opt = 3;
}
}
for(int j=i+1; j<=n; j++) q++,qr[q].x = a[j]-a[i],qr[q].opt = 2;
for(int j=1; j<=q; j++) qr[j].ang = qr[j].x.ang();
sort(qr+1,qr+q+1,cmp_qr);
for(int j=1; j<=q; j++)
{
l = qr[j].x;
if(qr[j].opt==1)
{
adr[qr[j].id] = s.insert(Element(stk[qr[j].id]));
}
else if(qr[j].opt==3)
{
s.erase(adr[qr[j].id]);
}
else if(qr[j].opt==2)
{
if(s.empty()) ans++;
else
{
Line mini = (*s.begin()).x;
double dis1 = calcdis(mini),dis2 = qr[j].x.x*qr[j].x.x+qr[j].x.y*qr[j].x.y;
if(dcmp(dis1-dis2)>0) ans++;
}
}
}
s.clear();
}
printf("%d\n",ans);
return 0;
}
BZOJ 4814 Luogu P3699 [CQOI2017]小Q的草稿 (计算几何、扫描线、set)的更多相关文章
- bzoj4814: [Cqoi2017]小Q的草稿
Description 小Q是个程序员.众所周知,程序员在写程序的时候经常需要草稿纸.小Q现在需要一张草稿纸用来画图,但是桌上 只有一张草稿纸,而且是一张被用过很多次的草稿纸.草稿纸可以看作一个二维平 ...
- bzoj 4814: [Cqoi2017]小Q的草稿【计算几何】
//先打个50暴力,10min50分简直美滋滋~ #include<iostream> #include<cstdio> #include<algorithm> u ...
- Luogu 3698 [CQOI2017]小Q的棋盘
BZOJ 4813 虽然数据范围很迷人,但是想树形$dp$没有前途. 先发现一个事情,就是我们可以先选择一条链,最后要走到这一条链上不回来,走到链上的点每一个只需要一步,而如果要走这条链之外的点,一个 ...
- luogu 3698 [CQOI2017]小Q的棋盘 树形dp
Code: #include <bits/stdc++.h> #define N 107 #define setIO(s) freopen(s".in","r ...
- bzoj 4813: [Cqoi2017]小Q的棋盘 [树形背包dp]
4813: [Cqoi2017]小Q的棋盘 题意: 某poj弱化版?树形背包 据说还可以贪心... #include <iostream> #include <cstdio> ...
- bzoj 4815: [Cqoi2017]小Q的表格 [数论]
4815: [Cqoi2017]小Q的表格 题意: 单点修改,查询前缀正方形和.修改后要求满足条件f(a,b)=f(b,a), b×f(a,a+b)=(a+b)*f(a,b) 一开始sb了认为一次只会 ...
- 【BZOJ4815】[CQOI2017]小Q的表格(莫比乌斯反演,分块)
[BZOJ4815][CQOI2017]小Q的表格(莫比乌斯反演,分块) 题面 BZOJ 洛谷 题解 神仙题啊. 首先\(f(a,b)=f(b,a)\)告诉我们矩阵只要算一半就好了. 接下来是\(b* ...
- BZOJ_4813_[Cqoi2017]小Q的棋盘_dfs
BZOJ_4813_[Cqoi2017]小Q的棋盘_dfs Description 小Q正在设计一种棋类游戏.在小Q设计的游戏中,棋子可以放在棋盘上的格点中.某些格点之间有连线,棋子只能 在有连线的格 ...
- 洛咕 P3700 [CQOI2017]小Q的表格
洛咕 P3700 [CQOI2017]小Q的表格 神仙题orz 首先推一下给的两个式子中的第二个 \(b\cdot F(a,a+b)=(a+b)\cdot F(a,b)\) 先简单的想,\(F(a,a ...
随机推荐
- Linux更改ext4根目录文件系统大小
首先通过lsblk 查看一下文件系统情况 然后通过fdisk /dev/sda类似命令,打开对应的磁盘管理,然后: 删除所有磁盘分区 重新建立一个更大的分区. 保存退出 再次通过lsblk查看分区大小 ...
- 【JavaScript】js中的构造函数,和构造函数的实例中的原型详解
1. 构造函数作为一个对象,他也有他的原型属性,即.prototype:该属性指向的原型对象是Object. 2. 而构造函数产生的实例却没有.prototype属性,但是作为一个对象,该实例却仍然拥 ...
- js之常用正则
//用户名正则,4到16位(字母,数字,下划线,减号) let uPattern = /^[a-zA-Z0-9_-]{4,16}$/; //密码强度正则,最少6位,包括至少1个大写字母,1个小写字母, ...
- 如何使用koa搭建一个简单服务
1.首先检测是否已经有node环境? 把Windows的黑窗体的命令行工具调用出来 敲击命令行node -v , 然后,就可以看到这个打印出了一个版本号,这就证明我们的node.js已经是安装 ...
- JavaScript中变量声明效率问题
1 var theString1 = "字符串1"; var theString2 = "字符串1"; var theString3 = "字符串1& ...
- CentOS 7.6 64位安装docker并设置开机启动
步骤如下 安装docker.docker-compose yum -y install docker-io docker-compose 启动docker service docker start 设 ...
- go语言入门(5)工程管理
在工程中不会简单到只有一个源代码文件,且源文件之间会有相互的依赖关系,早期Go语言使用makefile作为工程管理的临时方案,后来的Go命令行工具的革命性之处在于彻底消除了工程文件的概念,完全用目录结 ...
- spring framework体系结构及模块jar依赖关系
本文对于Spring的JAR包使用和配置,结合网友材料以spring 4.3.6.RELEASE版本为例,介绍spring框架结构和各模块对应JAR包以及模块间JAR依赖关系. 注:不同版本JAR包依 ...
- Linux 永久挂载镜像文件和制作yum源
Linux mount命令是经常会使用到的命令,它用于挂载Linux系统外的文件. 1.镜像挂载到系统指定目录下:[root@master cdrom]# mount -t auto /mnt/c ...
- python学习-数据类型
计算机处理的数据不单纯的指数字,计算机可以处理数字.文本.音频.视频等等各种数据,下面描述的是Python中可以直接使用和处理的基本数据类型. 整数 Python可以处理任意大小的整数,跟ja ...