【计算几何+极角排序+爆ll】E. Convex

https://www.bnuoj.com/v3/contest_show.php?cid=9147#problem/E

【题意】

给定n个点的坐标,可以选择其中的四个点构造凸四边形,问最多能构造多少个凸四边形?

【思路】

凸四边形的个数等于C(n,4)-凹四边形的个数。

凹四边形的特点是有一个顶点被另外三个顶点围成的三角形包了起来。

所以现在的问题就是找凹四边形。

我们可以枚举每个点,作为被三角形包围的中心点o。怎么找这样包围中心点的三角形?

这样的三角形一定是在存在一条经过中心点的直线,三角形的三个顶点在直线的同一侧。

那么枚举三角形的一个顶点x,另两个顶点一定在o和x的连线ox的上半平面内。而且这样做类似与尺取,只需O(n)的复杂度。

最后注意的一点是:
printf("%I64d\n",-3LL*n*(n-1)*(n-2)*(n-3)/24+cnt);

printf("%I64d\n",n*(n-1)*(n-2)*(n-3)/24LL-(n*(n-1)*(n-2)*(n-3)/6LL-cnt));

的区别。

前者在前面成了3LL,所以计算连乘的时候是把int转化为ll,不会爆

后者n*(n-1)*(n-2)*(n-3)在计算的过程中已经爆了。

解决办法有两种:
在前面乘以1LL;n变成ll

【Accelerate】

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<string>
 5 #include<cmath>
 6 #include<algorithm>
 7
 8 using namespace std;
 9 typedef long long ll;
10 const int maxn=710;
11 int n;
12 ll xx[maxn];
13 ll yy[maxn];
14 int cur;
15 double dis(ll x1,ll y1,ll x2,ll y2){return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));}
16 struct Point
17 {
18     ll x;
19     ll y;
20     double dis;
21     double alf;
22     Point(){}
23     Point(ll _x,ll _y):x(_x),y(_y){}
24     Point operator -(const Point &t) const
25     {
26         return Point(x-t.x,y-t.y);
27     }
28     ll operator ^(const Point &t)const
29     {
30         return (x*t.y)-(y*t.x);
31     }
32     double alfa()
33     {
34         if(y>yy[cur])return acos((x-xx[cur])/dis);
35         return -acos((x-xx[cur])/dis);
36     }
37 }p[maxn];
38
39 bool cmp(Point a,Point b)
40 {
41     if(b.x==xx[cur]&&b.y==yy[cur])
42     {
43         return true;
44     }
45     if(a.x==xx[cur]&&a.y==yy[cur])
46     {
47         return false;
48     }
49     return a.alf<b.alf;
50 }
51
52 int main()
53 {
54     int T;
55     scanf("%d",&T);
56     while(T--)
57     {
58         scanf("%d",&n);
59         for(int i=0;i<n;i++)
60         {
61             cin>>xx[i]>>yy[i];
62             p[i]=Point(xx[i],yy[i]);
63         }
64         ll cnt=0;
65         for(cur=0;cur<n;cur++)
66         {
67
68             int l=1;
69             Point o(xx[cur],yy[cur]);
70             for(int i=0;i<n;i++){p[i].dis=dis(p[i].x,p[i].y,xx[cur],yy[cur]);p[i].alf=p[i].alfa();}
71             sort(p,p+n,cmp);
72             for(int i=0;i<n-1;i++)
73             {
74                 while(((p[i]-o)^(p[l]-o))>0)
75                 {
76                     l=(l+1)%(n-1);
77                 }
78                 int len=(l-i-1+n-1)%(n-1);
79                 cnt+=len*(len-1)/2;
80             }
81         }
82     //    ll ans=n*(n-1)*(n-2)*(n-3)/24LL-(n*(n-1)*(n-2)*(n-3)/6LL-cnt);//注意,这样会爆
83     //    printf("%I64d\n",-3LL*n*(n-1)*(n-2)*(n-3)/24+cnt);//前面乘以3LL,不会爆
84         printf("%I64d\n",1LL*n*(n-1)*(n-2)*(n-3)/24LL-(1LL*n*(n-1)*(n-2)*(n-3)/6LL-cnt));
85     }
86     return 0;
87 }

【知识点】

判断是不是在一个半平面内用到了叉积的性质:

叉积的一个非常重要的性质是通过它的符号判断两向量相互之间的顺逆时针关系:设向量P=(x1,y1),Q=(x2,y2)
如果P*Q>0则P在Q的顺时针方向;
如果P*Q=0则P与Q共线,可能同向,与可能反向;
如果P*Q<0则P在Q的逆时针方向。

时间: 2024-08-17 04:53:56

【计算几何+极角排序+爆ll】E. Convex的相关文章

[POJ2007]Scrambled Polygon(计算几何 极角排序)

题目链接:http://poj.org/problem?id=2007 题意:给出凸包和起点,逆序输出. 极角排序可以用反三角函数求出角度,按照角度排序.也可以用叉乘来做.注意题目说给定第一个数据是0,0,这是凸包的起点,数据中有在x轴负半轴的数据,所以排序的时候0,0要跳过.只排1~n-1个坐标. 1 #include <algorithm> 2 #include <iostream> 3 #include <iomanip> 4 #include <cstri

hdu-5784 How Many Triangles(计算几何+极角排序)

题目链接: How Many Triangles Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 570    Accepted Submission(s): 183 Problem Description Alice has n points in two-dimensional plane. She wants to know ho

HDU 3532 Max Angle(计算几何——极角排序)

传送门 Max Angle Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 704    Accepted Submission(s): 253 Problem Description Given many points in a plane, two players are playing an interesting game. Pl

POJ Transmitters(计算几何 极角排序啊)

题目链接:http://poj.org/problem?id=1106 Description In a wireless network with multiple transmitters sending on the same frequencies, it is often a requirement that signals don't overlap, or at least that they don't conflict. One way of accomplishing thi

Gym 101986D Making Perimeter of the Convex Hull Shortest(凸包+极角排序)

首先肯定是构造一个完整的凸包包括所有的点,那么要使得刚好有两个点在外面,满足这个条件的只有三种情况. 1.两个在凸包上但是不连续的两个点. 2.两个在凸包上但是连续的两个点. 3.一个在凸包上,还有一个在这个点去掉后这段新凸包边上的一个点. 如何快速的截取新凸包的点是谁呢,我们可以将整个凸包划分区域,每个点删掉后,只可能在这块区域内选择新的点.那么我们就可以随机在凸包内部选择一个点,我使用的是凸包的重心作为坐标原点o,那么整个凸包移到原点处,然后在这个点的左侧和右侧的三角形区域内才是有可能构成新

【计算几何】【极角排序】【二分】Petrozavodsk Summer Training Camp 2016 Day 6: Warsaw U Contest, XVI Open Cup Onsite, Sunday, August 28, 2016 Problem J. Triangles

平面上给你n(不超过2000)个点,问你能构成多少个面积在[A,B]之间的Rt三角形. 枚举每个点作为直角顶点,对其他点极角排序,同方向的按长度排序,然后依次枚举每个向量,与其对应的另一条直角边是单调的,可以用一个pointer做出来,然后可以得出那些同方向的向量的区间(这个代码好像有点问题,可能会退化,最好确定了一个LL之后,对一个方向的不要重复算RR.这里如果也改成二分就比较好,复杂度不会退化).然后通过二分可以得到A使得面积在[A,B]间的有哪些(其实这个因为也是单调的,好像也没必要二分,

poj 1106 Transmitters (计算几何,叉积||极角排序)

Transmitters Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 4817   Accepted: 2576 Description In a wireless network with multiple transmitters sending on the same frequencies, it is often a requirement that signals don't overlap, or at

【计算几何】【凸包】【极角排序】【二分】Gym - 101128J - Saint John Festival

平面上n个红点,m个黑点,问你多少个黑点至少在一个红三角形内. 对红点求凸包后,转化为询问有多少个黑点在凸包内. 点在凸多边形内部判定,选定一个凸包上的点作原点,对凸包三角剖分,将其他的点极角排序之后,使用二分法就可以判定点在哪个剖分出来的三角形的夹角内,然后用叉积即可判定其在凸包内还是外,O(logn): http://www.cnblogs.com/dream-wind/archive/2012/05/23/2514694.html #include<cstdio> #include<

poj 2007 Scrambled Polygon(极角排序)

http://poj.org/problem?id=2007 Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 6701   Accepted: 3185 Description A closed polygon is a figure bounded by a finite number of line segments. The intersections of the bounding line segments ar