题目链接

(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)的更多相关文章

  1. bzoj4814: [Cqoi2017]小Q的草稿

    Description 小Q是个程序员.众所周知,程序员在写程序的时候经常需要草稿纸.小Q现在需要一张草稿纸用来画图,但是桌上 只有一张草稿纸,而且是一张被用过很多次的草稿纸.草稿纸可以看作一个二维平 ...

  2. bzoj 4814: [Cqoi2017]小Q的草稿【计算几何】

    //先打个50暴力,10min50分简直美滋滋~ #include<iostream> #include<cstdio> #include<algorithm> u ...

  3. Luogu 3698 [CQOI2017]小Q的棋盘

    BZOJ 4813 虽然数据范围很迷人,但是想树形$dp$没有前途. 先发现一个事情,就是我们可以先选择一条链,最后要走到这一条链上不回来,走到链上的点每一个只需要一步,而如果要走这条链之外的点,一个 ...

  4. luogu 3698 [CQOI2017]小Q的棋盘 树形dp

    Code: #include <bits/stdc++.h> #define N 107 #define setIO(s) freopen(s".in","r ...

  5. bzoj 4813: [Cqoi2017]小Q的棋盘 [树形背包dp]

    4813: [Cqoi2017]小Q的棋盘 题意: 某poj弱化版?树形背包 据说还可以贪心... #include <iostream> #include <cstdio> ...

  6. bzoj 4815: [Cqoi2017]小Q的表格 [数论]

    4815: [Cqoi2017]小Q的表格 题意: 单点修改,查询前缀正方形和.修改后要求满足条件f(a,b)=f(b,a), b×f(a,a+b)=(a+b)*f(a,b) 一开始sb了认为一次只会 ...

  7. 【BZOJ4815】[CQOI2017]小Q的表格(莫比乌斯反演,分块)

    [BZOJ4815][CQOI2017]小Q的表格(莫比乌斯反演,分块) 题面 BZOJ 洛谷 题解 神仙题啊. 首先\(f(a,b)=f(b,a)\)告诉我们矩阵只要算一半就好了. 接下来是\(b* ...

  8. BZOJ_4813_[Cqoi2017]小Q的棋盘_dfs

    BZOJ_4813_[Cqoi2017]小Q的棋盘_dfs Description 小Q正在设计一种棋类游戏.在小Q设计的游戏中,棋子可以放在棋盘上的格点中.某些格点之间有连线,棋子只能 在有连线的格 ...

  9. 洛咕 P3700 [CQOI2017]小Q的表格

    洛咕 P3700 [CQOI2017]小Q的表格 神仙题orz 首先推一下给的两个式子中的第二个 \(b\cdot F(a,a+b)=(a+b)\cdot F(a,b)\) 先简单的想,\(F(a,a ...

随机推荐

  1. CentOS 7安装Maven

    echo "安装Java环境,先安装JDK" yum -y install java-openjdk echo "切换到/usr/local/src下载目录" ...

  2. 怎样使用 vue-cli ( Vue 脚手架 )

    vue-cli 是 Vue 官方出品的快速构建单页应用的脚手架, 相当于 React 官方出品的 create-react-app , 下面演示 vue-cli 的 最 基本用法: 1. 全局安装 v ...

  3. 3-Perl 基础语法

    Perl 基础语法Perl借用了C.sed.awk.shell脚本以及很多其他编程语言的特性,语法与这些语言有些类似,也有自己的特点.Perl 程序有声明与语句组成,程序自上而下执行,包含了循环,条件 ...

  4. Scala学习八——继承

    一.本章要点 extends,final关键字和Java一样 重写方法时必须使用override 只有主构造器可以调用超类的构造器 可以重写字段 二.扩展类 Scala扩展类和Java一样(使用ext ...

  5. 解决IDEA报错Could not autowire. There is more than one bean of 'xxx' type

    更新项目之后IDEA突然出现了这样的报错信息.显示Could not autowire. There is more than one bean of 'xxx' type.这个错误的意思是xxx类型 ...

  6. 【大数据】初识Hadoop

    因为项目日志体量较大,每天有4-7T的日志量,传统的sqlserver已经不能满足,所以现在需要使用到大数据的相关工具进行记录和使用. 虽然公共项目提供了组件和解决方案,但是对于一些名词.概念还是有必 ...

  7. python常用模块:sys、os、path、setting、random、shutil

    今日内容讲了3个常用模块 一.sys模块二.os模块三.os下path模块四.random模块五.shutil模块 一.sys模块 import sys #环境变量 print(sys.path) # ...

  8. 2.java多线程_synchronized(Lock)同步

    1.synchronized同步关键词 线程安全是并发编程中的重要关注点,应该注意到的是,造成线程安全问题的主要诱因有两点,一是存在共享数据(也称临界资源),二是存在多条线程共同 操作共享数据.因此为 ...

  9. 一键登录已成大势所趋,Android端操作指南来啦!

    根据极光(Aurora Mobile)发布的<2019年Q2移动互联网行业数据研究报告>,2019年第二季度,移动网民人均安装APP总量已达56款.面对如此繁多的APP,想在用户的手机中占 ...

  10. unittest 报告——HTMLTestRunner/BSTestRunner+代码覆盖率

    1. HTMLTestRunner.py 代码(python3)如下: python2:  https://github.com/tungwaiyip/HTMLTestRunner "&qu ...