G - 郭大侠与阴阳家
给n个二维平面上的点,n属于[1,2000],x和y是[1,1000000000],唔,这题好像没用什么数据结构,可以用map,但是感觉强行map,不map感觉完全没问题
坑点有两个,重点,共线,重点简单,把所有点sort一遍,然后unique一发就可以,
共线,就需要先建立向量然后再处理了,
首先,能 组成平行四边形的条件是这两条向量平行且模长相等,所以我每个向量我就存储他的斜率和模长,还有向量所在直线与y轴的交点,当然这就涉及到一个问题,斜率为无穷时,而且此时向量所在直线与y轴没有焦点或有无穷个交点,这时候我就取一个很大的数1000010000,因为按所给题目的条件,这个数比所以可能的斜率都大,然后我对于这种情况,我存储它与x轴的交点,因为我存交点是为了判断共线,所以我只要这个交点能区分平行向量是否共线就行
然后,把这些向量sort,按斜率升序排序,斜率相同按模长升序排序,
然后就依次扫过去,处理那些平行且模长相等的向量,再来一个二重循环,枚举它们能组成多少个平行四边形
然后因为我们只判断了一组向量,实际中平行四边形的两组对边都是平行且模长相等的,所以我们得到的答案再除2就好了,另:反正我是用long long存的
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define ll long long #define maxn 2005 #define maxk 1000010000 int n; struct Node { ll x, y; bool operator <(Node a)const { return x < a.x || (x == a.x&&y < a.y); } bool operator ==(Node a)const { return (x == a.x) && (y == a.y); } }node[maxn]; struct Edge { ll length; double k, b; bool operator <(Edge t)const { if (fabs(k - t.k)>1e-6) return k < t.k; else return length < t.length; } }edge[maxn*maxn]; inline bool equal_v(Edge m, Edge n) { return fabs(m.k - n.k) < 1e-6&&m.length == n.length; } inline ll comb_2(ll x) { return x*(x - 1) / 2; } int main() { //freopen("input.txt", "r", stdin); scanf("%d", &n); for (int i = 0; i < n; ++i) scanf("%lld%lld", &node[i].x, &node[i].y); sort(node, node + n); n = unique(node, node + n) - node; int cnt = 0; ll ans = 0; for (int i = 0; i < n; ++i) { for (int j = i + 1; j < n; ++j) { if (node[j].x == node[i].x) { edge[cnt].k = maxk; edge[cnt].b = node[i].x; } else { edge[cnt].k = (node[j].y - node[i].y)*1.0 / (node[j].x - node[i].x); edge[cnt].b = node[i].y*1.0 - edge[cnt].k*node[i].x; } edge[cnt].length = (node[j].x - node[i].x)*(node[j].x - node[i].x) + (node[j].y - node[i].y)*(node[j].y - node[i].y); ++cnt; } } sort(edge, edge + cnt); /*for (int i = 0; i < cnt; ++i) printf("11 %f %f %f\n", edge[i].k, edge[i].a, edge[i].b); printf("\n");*/ /*for (int i = 0; i < cnt; ++i) printf("%f %f %f\n", edge[i].k, edge[i].a, edge[i].b); printf("\n");*/ for (int i = 0; i < cnt;) { int j; for (j = i + 1; j < cnt; ++j) { if (!equal_v(edge[i], edge[j])) break; } for (int k = i; k < j; ++k) { for (int l = k + 1; l < j; ++l) { if (fabs(edge[k].b - edge[l].b)>1e-6) ++ans; } } i = j; } ans >>= 1; printf("%lld\n", ans); //system("pause"); //while (1); return 0; }