【XSY3141】哲学家 计算几何 线段树
题目描述
有一个平面,最开始平面上没有任何点。
你要按顺序加入 \(n\) 个点,求加入每个点后有多少三角形严格包含原点(在边界上不算)。
\(n\leq 400000\),无重点。
题解
其实这题本来是强制在线的。
考虑不满足条件的三个顶点有什么特征。
先把每个点的极角求出来,可以发现,不满足条件的三个点以及原点组成的扇形的角度 \(\leq \pi\)。
那么满足条件的三角形个数就是总的三角形个数减掉不满足条件的三角形个数。
先把这些点按极角排序,记 \(c_i\) 为 \(i\) 右侧弧度范围为 \(\pi\) 以内的点的个数。
插入一个点 \(x\) 的时候,找到 \(x\) 左边 \(\pi\) 范围内最左的点 \(y\) 以及右边 \(\pi\) 范围内最右的点 \(z\),贡献就是 \(y\sim x\) 的 \(c_i\) 之和 \(+ x\sim z\) 中任取两个点的方案数。
用平衡树/线段树维护即可。
当两个点的极角之差很小的时候,要用叉积判断大小关系。
注意三点共线的情况。
时间复杂度:\(O(n\log n)\)
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef double db;
typedef long long ll;
const int N=400010;
const db eps=1;
const db pi=acos(-1);
struct point
{
ll x,y;
point(ll a=0,ll b=0):x(a),y(b){}
};
point operator -(const point &a,const point &b){return point(a.x-b.x,a.y-b.y);}
ll operator *(const point &a,const point &b){return a.x*b.y-a.y*b.x;}
point operator -(const point &a){return point(-a.x,-a.y);}
point a[N];
int n;
db ang[N];
int e[N];
struct pp
{
db ang;
point a;
int id;
pp(db x=0,point y=point(),int z=0):ang(x),a(y),id(z){}
};
pp f[N];
int operator <(pp a,pp b)
{
if(fabs(a.ang-b.ang)>eps)
return a.ang<b.ang;
ll s=a.a*b.a;
if(s!=0)
return s>0;
return a.id<b.id;
}
namespace seg
{
int t[1100000];
ll s[1100000];
int s2[1100000];
#define ls (p<<1)
#define rs ((p<<1)|1)
#define mid ((L+R)>>1)
void add(int p,int v)
{
t[p]+=v;
s[p]+=(ll)v*s2[p];
}
void push(int p)
{
if(t[p])
{
add(ls,t[p]);
add(rs,t[p]);
t[p]=0;
}
}
void add(int p,int l,int r,int v,int L,int R)
{
if(l<=L&&r>=R)
{
add(p,v);
return;
}
push(p);
if(l<=mid)
add(ls,l,r,v,L,mid);
if(r>mid)
add(rs,l,r,v,mid+1,R);
s[p]=s[ls]+s[rs];
}
void set(int p,int x,int L,int R)
{
if(L==R)
{
s2[p]=1;
return;
}
push(p);
if(x<=mid)
set(ls,x,L,mid);
else
set(rs,x,mid+1,R);
s2[p]=s2[ls]+s2[rs];
}
ll query1(int p,int l,int r,int L,int R)
{
if(l<=L&&r>=R)
return s[p];
push(p);
ll res=0;
if(l<=mid)
res+=query1(ls,l,r,L,mid);
if(r>mid)
res+=query1(rs,l,r,mid+1,R);
return res;
}
int query2(int p,int l,int r,int L,int R)
{
if(l<=L&&r>=R)
return s2[p];
push(p);
int res=0;
if(l<=mid)
res+=query2(ls,l,r,L,mid);
if(r>mid)
res+=query2(rs,l,r,mid+1,R);
return res;
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("c.in","r",stdin);
freopen("c.out","w",stdout);
#endif
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld%lld",&a[i].x,&a[i].y);
ang[i]=atan2(a[i].y,a[i].x);
if(!a[i].y&&a[i].x<0)
ang[i]=-pi;
}
for(int i=1;i<=n;i++)
f[i]=pp(ang[i],a[i],i);
sort(f+1,f+n+1);
for(int i=1;i<=n;i++)
e[f[i].id]=i;
int y,z;
ll s=0,ans;
for(int i=1;i<=n;i++)
{
if(ang[i]<-eps||(fabs(ang[i])<eps&&a[i]*point(1,0)>0))
{
y=lower_bound(f+1,f+n+1,pp(ang[i]+pi,-a[i],0))-f;
if(y<=n)
{
s+=seg::query1(1,y,n,1,n);
seg::add(1,y,n,1,1,n);
}
s+=seg::query1(1,1,e[i],1,n);
z=upper_bound(f+1,f+n+1,pp(ang[i]+pi,-a[i],n+1))-f-1;
if(y<=z)
{
ll w=seg::query2(1,y,z,1,n);
s-=w*(w-1)/2;
ll x=seg::query2(1,lower_bound(f+1,f+n+1,pp(ang[i],a[i],0))-f,e[i],1,n);
s-=x*w;
}
ll tmp=seg::query2(1,e[i],z,1,n);
s+=tmp*(tmp-1)/2;
seg::set(1,e[i],1,n);
if(e[i]>1)
seg::add(1,1,e[i]-1,1,1,n);
seg::add(1,e[i],e[i],tmp,1,n);
}
else
{
y=lower_bound(f+1,f+n+1,pp(ang[i]-pi,-a[i],0))-f;
s+=seg::query1(1,y,e[i],1,n);
z=upper_bound(f+1,f+n+1,pp(ang[i]-pi,-a[i],n+1))-f-1;
if(y<=z)
{
ll w=seg::query2(1,y,z,1,n);
s-=w*(w-1)/2;
ll x=seg::query2(1,lower_bound(f+1,f+n+1,pp(ang[i],a[i],0))-f,e[i],1,n);
s-=x*w;
}
ll tmp=0;
if(z>0)
tmp+=seg::query2(1,1,z,1,n);
tmp+=seg::query2(1,e[i],n,1,n);
s+=tmp*(tmp-1)/2;
seg::set(1,e[i],1,n);
if(e[i]>y)
seg::add(1,y,e[i]-1,1,1,n);
seg::add(1,e[i],e[i],tmp,1,n);
}
ans=(ll)i*(i-1)*(i-2)/6-s;
printf("%lld\n",ans);
}
return 0;
}
【XSY3141】哲学家 计算几何 线段树的更多相关文章
- 2019牛客多校第八场 F题 Flowers 计算几何+线段树
2019牛客多校第八场 F题 Flowers 先枚举出三角形内部的点D. 下面所说的旋转没有指明逆时针还是顺时针则是指逆时针旋转. 固定内部点的答案的获取 anti(A)anti(A)anti(A)或 ...
- POJ 2991 Crane(线段树+计算几何)
POJ 2991 Crane 题目链接 题意:给定一个垂直的挖掘机臂.有n段,如今每次操作能够旋转一个位置,把[s, s + 1]专程a度,每次旋转后要输出第n个位置的坐标 思路:线段树.把每一段当成 ...
- Codeforces Gym100543B 计算几何 凸包 线段树 二分/三分 卡常
原文链接https://www.cnblogs.com/zhouzhendong/p/CF-Gym100543B.html 题目传送门 - CF-Gym100543B 题意 给定一个折线图,对于每一条 ...
- LOJ2401 JOISC2017 Dragon2 计算几何、线段树
传送门 先考虑每一个攻击方的龙和被攻击方的龙可以与多少个被攻击方/攻击方的龙匹配. 对于攻击方的龙\(A\)和被攻击方的龙\(B\),在道路为线段\((C,D)\)的情况下,能够与下图位置的所有对应属 ...
- POJ 3667 Hotel(线段树 区间合并)
Hotel 转载自:http://www.cnblogs.com/scau20110726/archive/2013/05/07/3065418.html [题目链接]Hotel [题目类型]线段树 ...
- 线段树(单标记+离散化+扫描线+双标记)+zkw线段树+权值线段树+主席树及一些例题
“队列进出图上的方向 线段树区间修改求出总量 可持久留下的迹象 我们 俯身欣赏” ----<膜你抄> 线段树很早就会写了,但一直没有总结,所以偶尔重写又会懵逼,所以还是要总结一下. ...
- POJ 3667 线段树区间合并
http://www.cnblogs.com/scau20110726/archive/2013/05/07/3065418.html 用线段树,首先要定义好线段树的节点信息,一般看到一个问题,很难很 ...
- 【BZOJ 3165】 [Heoi2013]Segment 李超线段树
所谓李超线段树就是解决此题一类的问题(线段覆盖查询点最大(小)),把原本计算几何的题目变成了简单的线段树,巧妙地结合了线段树的标记永久化与标记下传,在不考虑精度误差的影响下,打法应该是这样的. #in ...
- poj 3667 Hotel (线段树的合并操作)
Hotel The cows are journeying north to Thunder Bay in Canada to gain cultural enrichment and enjoy a ...
随机推荐
- thymeleaf的配置
1.在springboto项目中使用thymeleaf标签,必须先添加依赖,如下. <dependency> <groupId>org.springframework.boot ...
- SAP MM 根据采购订单反查采购申请?
SAP MM 根据采购订单反查采购申请? 前日微信上某同行发来一个message,说是想知道如何通过采购订单号查询到其前端的采购申请号. 笔者首先想到去检查采购订单相关的常用报表ME2L/ME2M/M ...
- Android为TV端助力 播放视频卡顿问题
问题分析: 1.连接服务器,ping IP 看看有没有丢包 2.写一个只有mediaplayer的Demo,放到同款的盒子或者电视,保证网咯也是一样的情况下,看看Demo卡不卡 如果一直不卡,那有可能 ...
- go语言打造个人博客系统(二)
go语言打造个人博客系统(二) 在上篇文章go语言打造个人博客系统(一)中,我们了解了go语言的优点和go语言的数据库操作,本次我们会完成博客系统的后端开发. 博客系统后端接口开发 路由测试 ht ...
- python 迭代器协议和生成器
一.什么是迭代器协议 1.迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个stoplteration异常,以终止迭代(只能往后走,不能往前退) 2.可迭代 ...
- c/c++ linux epoll系列2 利用epoll_wait查看是否可以送信
linux epoll系列2 利用epoll_wait查看是否可以送信 write函数本来是非阻塞函数,但是当缓存区被写满后,再往缓存区里写的时候,就必须等待缓存区再次变成可写,所以这是write就变 ...
- 5.4Python数据处理篇之Sympy系列(四)---微积分
目录 目录 前言 (一)求导数-diff() 1.一阶求导-diff() 2.多阶求导-diff() 3.求偏导数-diff() (二)求积分-integrate() (三)求极限-limit() ( ...
- CORS——跨域请求那些事儿
在日常的项目开发时会不可避免的需要进行跨域操作,而在实际进行跨域请求时,经常会遇到类似 No 'Access-Control-Allow-Origin' header is present on th ...
- P1273 有线电视网
题目描述 某收费有线电视网计划转播一场重要的足球比赛.他们的转播网和用户终端构成一棵树状结构,这棵树的根结点位于足球比赛的现场,树叶为各个用户终端,其他中转站为该树的内部节点. 从转播站到转播站以及从 ...
- 洛谷 P1226 【模板】快速幂||取余运算
题目链接 https://www.luogu.org/problemnew/show/P1226 题目描述 输入b,p,k的值,求b^p mod k的值.其中b,p,k*k为长整型数. 输入输出格式 ...