求半径d<=50000的圆(不含边界)内n<=50000条直线有多少交点,给直线的解析式。

一开始就想,如果能求出直线交点与原点距离<d的条件,那么从中不重复地筛选即可。然而两个kx+b联立起来加勾股定理特别丑。。

换个想法,一条线在圆上就截了两个点。把这些点做极角排序后(即从y轴正半轴的射线顺时针扫一圈,把依次遇到的点排下来)后,每条直线就可以两个点表示。设其极角排序后,序较小的那个点叫A,另一个叫B。

其实就是:对所有(Ai,Bi),求有多少j满足Aj<Ai且Ai<Bj<Bi,其中小于号是极角序比较。

这就好比:给若干线段,求有多少对线段相交而不包含。也就是对所有Li,Ri,求有多少Lj<Li并且Li<Rj<Ri。也就是,把原来一条直线看成两个点,两个点按极角序编号,两个点间的弧的交拉直成线段交,求这些线段有多少对交,就变成很裸的扫描线。

 #include<stdio.h>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
#include<math.h>
//#include<iostream>
using namespace std; int n,d;
#define maxn 100011
const double eps=1e-,inf=1e15;
struct Line
{
double k,b;
}a[maxn];
struct Point
{
double x,y,t;int k,id;
bool operator < (const Point &b) const
{return k<b.k || (k==b.k && t>b.t);}
bool operator == (const Point &b) const
{return fabs(x-b.x)<eps && fabs(y-b.y)<eps;}
bool operator != (const Point &b) const {return !(*this==b);}
}p[maxn];int lp=;
double x,y,z;
#define LL long long
void addp(double x,double y,int id)
{
Point &e=p[++lp];
e.x=x;e.y=y;e.id=id;
e.t=x?y/x:inf;
if (x>= && y>) e.k=;
else if (x> && y<=) e.k=;
else if (x<= && y<) e.k=;
else e.k=;
}
void makep(int x)
{
if (a[x].k==inf)
{
if (a[x].b-d>eps || a[x].b+d<-eps) return;
addp(a[x].b,sqrt(1.0*d*d-a[x].b*a[x].b),x);
addp(a[x].b,-sqrt(1.0*d*d-a[x].b*a[x].b),x);
}
else
{
double u=a[x].k*a[x].k+,v=*a[x].k*a[x].b,w=a[x].b*a[x].b-d*d;
if (v*v-*u*w<-eps) return;
double tmp=(-v+sqrt(v*v-*u*w))/(*u);
addp(tmp,a[x].k*tmp+a[x].b,x);
tmp=(-v-sqrt(v*v-*u*w))/(*u);
addp(tmp,a[x].k*tmp+a[x].b,x);
}
}
struct BIT
{
int a[maxn],n;
void clear(int n) {memset(a,,sizeof(a));this->n=n;}
void add(int x,int v) {for (;x<=n;x+=x&-x) a[x]+=v;}
int query(int x) {int ans=;for (;x;x-=x&-x) ans+=a[x];return ans;}
}t;
struct seg
{
int l,r;
bool operator < (const seg &b) const {return l<b.l;}
}b[maxn];
bool vis[maxn];
int main()
{
scanf("%d%d",&n,&d);
for (int i=;i<=n;i++)
{
scanf("%lf%lf%lf",&x,&y,&z);
a[i].k=y?-x/y:inf;
a[i].b=y?-z/y:-z/x;
makep(i);
}
sort(p+,p++lp);
memset(vis,,sizeof(vis));
p[lp+].x=inf;p[lp+].y=inf;
int cnt=,last=;
for (int i=;i<=lp+;i++) if (p[i]!=p[i-])
{
cnt++;
for (int &j=last;j<i;j++)
if (vis[p[j].id]) b[p[j].id].r=cnt;
else vis[p[j].id]=,b[p[j].id].l=cnt;
}
for (int i=;i<=n;i++) if (!vis[i]) b[i].l=b[i].r=0x3f3f3f3f;
sort(b+,b++n);
LL ans=;last=;
t.clear(cnt);
for (int i=;i<=(lp>>)+;i++) if (b[i].l!=b[i-].l)
{
for (int j=last;j<i;j++)
ans+=t.query(b[j].r-)-t.query(b[j].l);
for (int &j=last;j<i;j++)
t.add(b[j].r,);
}
printf("%lld\n",ans);
return ;
}

BZOJ1573: [Usaco2009 Open]牛绣花cowemb的更多相关文章

  1. 【树状数组 离散化】bzoj1573: [Usaco2009 Open]牛绣花cowemb

    解方程题! Description Bessie学会了刺绣这种精细的工作.牛们在一片半径为d(1 <= d <= 50000)的圆形布上绣花. 它们一共绣了N (2 <= N < ...

  2. NOIP2018 - 暑期博客整理

    暑假写的一些博客复习一遍.顺便再写一遍或者以现在的角度补充一点东西. 盛暑七月 初涉基环外向树dp&&bzoj1040: [ZJOI2008]骑士 比较经典的基环外向树dp.可以借鉴的 ...

  3. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  4. BZOJ3403: [Usaco2009 Open]Cow Line 直线上的牛

    3403: [Usaco2009 Open]Cow Line 直线上的牛 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 48  Solved: 41[S ...

  5. BZOJ 3403: [Usaco2009 Open]Cow Line 直线上的牛( deque )

    直接用STL的的deque就好了... ---------------------------------------------------------------------- #include& ...

  6. 3403: [Usaco2009 Open]Cow Line 直线上的牛

    3403: [Usaco2009 Open]Cow Line 直线上的牛 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 71  Solved: 62[S ...

  7. 【BZOJ】3403: [Usaco2009 Open]Cow Line 直线上的牛(模拟)

    http://www.lydsy.com/JudgeOnline/problem.php?id=3404 裸的双端队列.. #include <cstdio> #include <c ...

  8. B3403 [Usaco2009 Open]Cow Line 直线上的牛 deque

    deque真的秀,queue和stack...没啥用了啊.操作差不多,就是在前面加一个front||back_就行了. 题干: 题目描述 题目描述     约翰的N只奶牛(编为1到N号)正在直线上排队 ...

  9. BZOJ 3403: [Usaco2009 Open]Cow Line 直线上的牛(模拟)

    直接双端队列模拟,完了= = CODE: #include<cstdio>#include<algorithm>#include<iostream>#include ...

随机推荐

  1. 初识jstl标签库

    JSTL(JSP Standard Tag Library,JSP标准标签库) 是一个不断完善的开源的 JSP 标签库,是由 apache 的 jakarta 小组来维护的,根据 JST L标签所提供 ...

  2. PKU_campus_2017_K Lying Island

    思路: 题目链接http://poj.openjudge.cn/practice/C17K/ 状压dp.dp[i][j]表示第i - k人到第i人的状态为j的情况下前i人中最多有多少好人. 实现: # ...

  3. java操作Excel、PDF文件

    java操作Excel.PDF文件 分享者:Vashon 分享来源:CSDN博客 下面这些是在开发中用到的一些东西,有的代码贴的不是完整的,只是贴出了关于操作EXCEL的代码: jxl是一个*国人写的 ...

  4. Java子类与父类方法的隐藏和覆盖

    class Base{     int x = 1;     static int y = 2;     String name(){         return "mother" ...

  5. 登录脚本重构by封装

    package com.gubai.selenium; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; imp ...

  6. postman对登陆进行压力测试的方法

    1.填写完整参数,设置好变量,选择好环境,保存好 2.将变量mobile_phone和password的值以如下图的格式,填写到Excel表格中,然后以csv(逗号分隔)的形式进行保存 3.点击此测试 ...

  7. 在移动端实现1px的边框

    由于分辨率 DPI 的差异,高清手机屏上的 1px 实际上是由 2×2 个像素点来渲染,有的屏幕甚至用到了 3×3 个像素点 所以 border: 1px 在移动端会渲染为 2px 的边框 与设计图产 ...

  8. 彻底卸载WIN10 OneDrive

    彻底卸载WIN10 OneDrive @ECHO OFF %SystemRoot%\SysWOW64\OneDriveSetup.exe /uninstall RD "%UserProfil ...

  9. 3. 对系统表空间使用Raw磁盘分区

    3. 对系统表空间使用Raw磁盘分区 可以将raw磁盘分区用作InnoDB系统表空间中的数据文件.此技术可在Windows和某些Linux和Unix系统上启用非缓冲I/O,而无需文件系统开销.使用和不 ...

  10. Linux test命令

    test命令 长格式的例子: test "$A" == "$B" && echo "Strings are equal" t ...