Farmer John would like to create a triangular pasture for his cows.
There are NN fence posts (3≤N≤1053≤N≤105) at distinct points (X1,Y1)…(XN,YN)(X1,Y1)…(XN,YN) on the 2D map of his farm. He can choose three of them to form the vertices of the triangular pasture as long as one of the sides of the triangle is parallel to the xx-axis and another side is parallel to the yy-axis.
What is the sum of the areas of all possible pastures that FJ can form?
The first line contains N.N.Each of the next NN lines contains two integers XiXi and YiYi, each in the range −104…104−104…104 inclusive, describing the location of a fence post.
As the sum of areas is not necessarily be an integer and may be very large, output the remainder when two times the sum of areas is taken modulo 109+7109+7.
4 0 0 0 1 1 0 1 2
3
Fence posts (0,0)(0,0), (1,0)(1,0), and (1,2)(1,2) give a triangle of area 11, while (0,0)(0,0), (1,0)(1,0), and (0,1)(0,1) give a triangle of area 0.50.5. Thus, the answer is 2⋅(1+0.5)=3.2⋅(1+0.5)=3.
Problem credits: Travis Hance and Nick Wu
[/hide]
(Analysis by Benjamin Qi)
Suppose that we want to find two times the sum of areas of all triangles with right angle at (X1,Y1)(X1,Y1). Let A1={Yi|Xi=X1}A1={Yi|Xi=X1} (the set of YY-coordinates for all points that share the same XX-coordinate as post 11) and B1={Xj|Yj=Y1}B1={Xj|Yj=Y1}. Then the desired quantity will equal
It remains to compute the value of ∑x∈Bi|Xi−x|∑x∈Bi|Xi−x| for every ii. The summation involving yy can be computed similarly.
What we need to do, restated more simply:
This can be done in linear time. First, compute s1s1. Then for all 1≤i<N1≤i<N, si+1=si+(2i−N)(xi+1−xi).si+1=si+(2i−N)(xi+1−xi).
Overall, the solution runs in O(NlogN)O(NlogN) time because we first need to sort the xx-coordinates for each yy.
#include <bits/stdc++.h> using namespace std; typedef long long ll; #define f first #define s second const int MOD = 1e9+7; void setIO(string s) { ios_base::sync_with_stdio(0); cin.tie(0); freopen((s+".in").c_str(),"r",stdin); freopen((s+".out").c_str(),"w",stdout); } struct mi { int v; explicit operator int() const { return v; } mi(ll _v) : v(_v%MOD) { v += (v<0)*MOD; } mi() : mi(0) {} }; mi operator+(mi a, mi b) { return mi(a.v+b.v); } mi operator-(mi a, mi b) { return mi(a.v-b.v); } mi operator*(mi a, mi b) { return mi((ll)a.v*b.v); } int N; vector<pair<int,int>> v; vector<mi> sum[100005]; vector<pair<int,int>> todo[20001]; void check() { for (int i = 0; i <= 20000; ++i) if (todo[i].size() > 0) { int sz = todo[i].size(); sort(begin(todo[i]),end(todo[i])); mi cur = 0; for (int j = 0; j < sz; ++j) cur = cur+todo[i][j].f-todo[i][0].f; for (int j = 0; j < sz; ++j) { if (j) cur = cur+(2*j-sz)*(todo[i][j].f-todo[i][j-1].f); sum[todo[i][j].s].push_back(cur); } } } int main() { setIO("triangles"); cin >> N; v.resize(N); for (int i = 0; i < N; ++i) cin >> v[i].f >> v[i].s; for (int i = 0; i <= 20000; ++i) todo[i].clear(); for (int i = 0; i < N; ++i) todo[v[i].f+10000].push_back({v[i].s,i}); check(); for (int i = 0; i <= 20000; ++i) todo[i].clear(); for (int i = 0; i < N; ++i) todo[v[i].s+10000].push_back({v[i].f,i}); check(); mi ans = 0; for (int i = 0; i < N; ++i) ans = ans+sum[i][0]*sum[i][1]; cout << ans.v << "\n"; }
[/hide]
© 2024. All Rights Reserved. 沪ICP备2023009024号-1