题目描述

  有一个平面,最开始平面上没有任何点。

  你要按顺序加入 \(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;
}

最新文章

  1. Unicode和UTF-8的关系
  2. jstl 小总结 以及 jstl fn
  3. 理解button标签的默认行为
  4. 【SSO单点系列】(1):CAS4.0 环境的搭建
  5. OpenGL 小游戏 贪吃蛇1(2D)
  6. Microsoft Enterprise Library 5.0 缓存配置
  7. LeetCode OJ--Swap Nodes in Pairs
  8. linux中断申请之request_threaded_irq
  9. 安装JAVA JDK注意事项
  10. unity中数据的持久化存储
  11. 希尔排序----java实现
  12. Ext.ux.form.SuperBoxSelect
  13. Ubuntu 简单安装和配置 GitLab
  14. Centos7系统安装部署docker
  15. tensor flow中summary用法总结
  16. 【转】这五种方法前四种方法只支持IE浏览器,最后一个方法支持当前主流的浏览器(火狐,IE,Chrome,Opera,Safari)
  17. vuex 的基本使用之Module
  18. day02 运算符和编码
  19. 利用solr实现商品的搜索功能
  20. 纯绿色 jsonUtil工具

热门文章

  1. AI时代大点兵-国内外知名AI公司2018年最新盘点
  2. 从.Net到Java学习第五篇——Spring Boot &amp;&amp;Profile &amp;&amp;Swagger2
  3. Android细笔记--DataStorage
  4. Android studio,第一个生成,调用成功的jni(说多了都是泪)
  5. [安卓]ListView 与 RecyclerView的比较
  6. ASP.NET Core 入门教程 7、ASP.NET Core MVC 分部视图入门
  7. asp.net core 2.1 部署 centos7
  8. Windows Server 2012 NIC Teaming 网卡绑定介绍及注意事项
  9. Linux 中NFS服务器的搭建
  10. 前后端分离djangorestframework——解决跨域请求