题目描述

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

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

代码

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #include<cmath>
  5. using namespace std;
  6. typedef double db;
  7. typedef long long ll;
  8. const int N=400010;
  9. const db eps=1;
  10. const db pi=acos(-1);
  11. struct point
  12. {
  13. ll x,y;
  14. point(ll a=0,ll b=0):x(a),y(b){}
  15. };
  16. point operator -(const point &a,const point &b){return point(a.x-b.x,a.y-b.y);}
  17. ll operator *(const point &a,const point &b){return a.x*b.y-a.y*b.x;}
  18. point operator -(const point &a){return point(-a.x,-a.y);}
  19. point a[N];
  20. int n;
  21. db ang[N];
  22. int e[N];
  23. struct pp
  24. {
  25. db ang;
  26. point a;
  27. int id;
  28. pp(db x=0,point y=point(),int z=0):ang(x),a(y),id(z){}
  29. };
  30. pp f[N];
  31. int operator <(pp a,pp b)
  32. {
  33. if(fabs(a.ang-b.ang)>eps)
  34. return a.ang<b.ang;
  35. ll s=a.a*b.a;
  36. if(s!=0)
  37. return s>0;
  38. return a.id<b.id;
  39. }
  40. namespace seg
  41. {
  42. int t[1100000];
  43. ll s[1100000];
  44. int s2[1100000];
  45. #define ls (p<<1)
  46. #define rs ((p<<1)|1)
  47. #define mid ((L+R)>>1)
  48. void add(int p,int v)
  49. {
  50. t[p]+=v;
  51. s[p]+=(ll)v*s2[p];
  52. }
  53. void push(int p)
  54. {
  55. if(t[p])
  56. {
  57. add(ls,t[p]);
  58. add(rs,t[p]);
  59. t[p]=0;
  60. }
  61. }
  62. void add(int p,int l,int r,int v,int L,int R)
  63. {
  64. if(l<=L&&r>=R)
  65. {
  66. add(p,v);
  67. return;
  68. }
  69. push(p);
  70. if(l<=mid)
  71. add(ls,l,r,v,L,mid);
  72. if(r>mid)
  73. add(rs,l,r,v,mid+1,R);
  74. s[p]=s[ls]+s[rs];
  75. }
  76. void set(int p,int x,int L,int R)
  77. {
  78. if(L==R)
  79. {
  80. s2[p]=1;
  81. return;
  82. }
  83. push(p);
  84. if(x<=mid)
  85. set(ls,x,L,mid);
  86. else
  87. set(rs,x,mid+1,R);
  88. s2[p]=s2[ls]+s2[rs];
  89. }
  90. ll query1(int p,int l,int r,int L,int R)
  91. {
  92. if(l<=L&&r>=R)
  93. return s[p];
  94. push(p);
  95. ll res=0;
  96. if(l<=mid)
  97. res+=query1(ls,l,r,L,mid);
  98. if(r>mid)
  99. res+=query1(rs,l,r,mid+1,R);
  100. return res;
  101. }
  102. int query2(int p,int l,int r,int L,int R)
  103. {
  104. if(l<=L&&r>=R)
  105. return s2[p];
  106. push(p);
  107. int res=0;
  108. if(l<=mid)
  109. res+=query2(ls,l,r,L,mid);
  110. if(r>mid)
  111. res+=query2(rs,l,r,mid+1,R);
  112. return res;
  113. }
  114. }
  115. int main()
  116. {
  117. #ifndef ONLINE_JUDGE
  118. freopen("c.in","r",stdin);
  119. freopen("c.out","w",stdout);
  120. #endif
  121. scanf("%d",&n);
  122. for(int i=1;i<=n;i++)
  123. {
  124. scanf("%lld%lld",&a[i].x,&a[i].y);
  125. ang[i]=atan2(a[i].y,a[i].x);
  126. if(!a[i].y&&a[i].x<0)
  127. ang[i]=-pi;
  128. }
  129. for(int i=1;i<=n;i++)
  130. f[i]=pp(ang[i],a[i],i);
  131. sort(f+1,f+n+1);
  132. for(int i=1;i<=n;i++)
  133. e[f[i].id]=i;
  134. int y,z;
  135. ll s=0,ans;
  136. for(int i=1;i<=n;i++)
  137. {
  138. if(ang[i]<-eps||(fabs(ang[i])<eps&&a[i]*point(1,0)>0))
  139. {
  140. y=lower_bound(f+1,f+n+1,pp(ang[i]+pi,-a[i],0))-f;
  141. if(y<=n)
  142. {
  143. s+=seg::query1(1,y,n,1,n);
  144. seg::add(1,y,n,1,1,n);
  145. }
  146. s+=seg::query1(1,1,e[i],1,n);
  147. z=upper_bound(f+1,f+n+1,pp(ang[i]+pi,-a[i],n+1))-f-1;
  148. if(y<=z)
  149. {
  150. ll w=seg::query2(1,y,z,1,n);
  151. s-=w*(w-1)/2;
  152. ll x=seg::query2(1,lower_bound(f+1,f+n+1,pp(ang[i],a[i],0))-f,e[i],1,n);
  153. s-=x*w;
  154. }
  155. ll tmp=seg::query2(1,e[i],z,1,n);
  156. s+=tmp*(tmp-1)/2;
  157. seg::set(1,e[i],1,n);
  158. if(e[i]>1)
  159. seg::add(1,1,e[i]-1,1,1,n);
  160. seg::add(1,e[i],e[i],tmp,1,n);
  161. }
  162. else
  163. {
  164. y=lower_bound(f+1,f+n+1,pp(ang[i]-pi,-a[i],0))-f;
  165. s+=seg::query1(1,y,e[i],1,n);
  166. z=upper_bound(f+1,f+n+1,pp(ang[i]-pi,-a[i],n+1))-f-1;
  167. if(y<=z)
  168. {
  169. ll w=seg::query2(1,y,z,1,n);
  170. s-=w*(w-1)/2;
  171. ll x=seg::query2(1,lower_bound(f+1,f+n+1,pp(ang[i],a[i],0))-f,e[i],1,n);
  172. s-=x*w;
  173. }
  174. ll tmp=0;
  175. if(z>0)
  176. tmp+=seg::query2(1,1,z,1,n);
  177. tmp+=seg::query2(1,e[i],n,1,n);
  178. s+=tmp*(tmp-1)/2;
  179. seg::set(1,e[i],1,n);
  180. if(e[i]>y)
  181. seg::add(1,y,e[i]-1,1,1,n);
  182. seg::add(1,e[i],e[i],tmp,1,n);
  183. }
  184. ans=(ll)i*(i-1)*(i-2)/6-s;
  185. printf("%lld\n",ans);
  186. }
  187. return 0;
  188. }

【XSY3141】哲学家 计算几何 线段树的更多相关文章

  1. 2019牛客多校第八场 F题 Flowers 计算几何+线段树

    2019牛客多校第八场 F题 Flowers 先枚举出三角形内部的点D. 下面所说的旋转没有指明逆时针还是顺时针则是指逆时针旋转. 固定内部点的答案的获取 anti(A)anti(A)anti(A)或 ...

  2. POJ 2991 Crane(线段树+计算几何)

    POJ 2991 Crane 题目链接 题意:给定一个垂直的挖掘机臂.有n段,如今每次操作能够旋转一个位置,把[s, s + 1]专程a度,每次旋转后要输出第n个位置的坐标 思路:线段树.把每一段当成 ...

  3. Codeforces Gym100543B 计算几何 凸包 线段树 二分/三分 卡常

    原文链接https://www.cnblogs.com/zhouzhendong/p/CF-Gym100543B.html 题目传送门 - CF-Gym100543B 题意 给定一个折线图,对于每一条 ...

  4. LOJ2401 JOISC2017 Dragon2 计算几何、线段树

    传送门 先考虑每一个攻击方的龙和被攻击方的龙可以与多少个被攻击方/攻击方的龙匹配. 对于攻击方的龙\(A\)和被攻击方的龙\(B\),在道路为线段\((C,D)\)的情况下,能够与下图位置的所有对应属 ...

  5. POJ 3667 Hotel(线段树 区间合并)

    Hotel 转载自:http://www.cnblogs.com/scau20110726/archive/2013/05/07/3065418.html [题目链接]Hotel [题目类型]线段树 ...

  6. 线段树(单标记+离散化+扫描线+双标记)+zkw线段树+权值线段树+主席树及一些例题

    “队列进出图上的方向 线段树区间修改求出总量 可持久留下的迹象 我们 俯身欣赏” ----<膜你抄>     线段树很早就会写了,但一直没有总结,所以偶尔重写又会懵逼,所以还是要总结一下. ...

  7. POJ 3667 线段树区间合并

    http://www.cnblogs.com/scau20110726/archive/2013/05/07/3065418.html 用线段树,首先要定义好线段树的节点信息,一般看到一个问题,很难很 ...

  8. 【BZOJ 3165】 [Heoi2013]Segment 李超线段树

    所谓李超线段树就是解决此题一类的问题(线段覆盖查询点最大(小)),把原本计算几何的题目变成了简单的线段树,巧妙地结合了线段树的标记永久化与标记下传,在不考虑精度误差的影响下,打法应该是这样的. #in ...

  9. poj 3667 Hotel (线段树的合并操作)

    Hotel The cows are journeying north to Thunder Bay in Canada to gain cultural enrichment and enjoy a ...

随机推荐

  1. 常用weblogic搜索关键字

    NOTE:876004.1 - How to Apply WebLogic Server (WLS) Patches Using Smart Update [Video]NOTE:942815.1 - ...

  2. Webpack4教程:第一部分,入口、输入和ES6模块

    转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 原文出处:https://wanago.io/2018/07/16/webpack-4-course-par ...

  3. Python开发爬虫之BeautifulSoup解析网页篇:爬取安居客网站上北京二手房数据

    目标:爬取安居客网站上前10页北京二手房的数据,包括二手房源的名称.价格.几室几厅.大小.建造年份.联系人.地址.标签等. 网址为:https://beijing.anjuke.com/sale/ B ...

  4. Android 网络框架 OKHttp3

    概述 OKHttp是一个处理网络请求的框架,其优点有,支持http2,对一台机器的所有请求共享同一个socket. 内置连接池,支持连接复用,减少延迟.通过缓存避免重复的请求,请求失败时自动重试主机的 ...

  5. InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised.解决办法

    最近使用requests进行get请求的时候,控制台输出如下错误. InsecureRequestWarning: Unverified HTTPS request is being made. Ad ...

  6. 安装Linux内核源代码

    系统:Ubuntu 18 CPU架构:AMD64 1,在终端输入:sudo apt install linux-source 命令 2,进入/usr/src/linux-source-4.15.0目录 ...

  7. Servlet是否单例?

    1,测试环境: Java SE版本:1.8.0_161(AMD64) Tomcat版本:9.0.7(AMD64) 2,试验 (1)编写HelloServlet. 由于测试代码很简单,此处只列出doGe ...

  8. zabbix忘记admin登录密码重置密码

    问题描述: 有时候忘记admin的密码了,因为账号太多 解决方案: 1.zabbix连接的是mysql数据库 [root@localhost /]# mysql -uroot -pAbc123 #-u ...

  9. AnyDesk远程连接及异常处理

    远程协助工具,用得最普遍的非QQ莫属,毕竟用户量在这里摆着的.不过,用户体验效果还不太理想,你懂得.接下来分享两个工具,一个是TeamViewer,另一个是AnyDesk.你更倾向于哪一款呢? 一.T ...

  10. pymsql模块

    老师的博客地址:http://www.cnblogs.com/wupeiqi/articles/5713330.html 通过pymysql 模块可以通过朋友去操作mysql 数据库,首先的在pip上 ...