Problem H
Counting Rectangles
Input: Standard Input
Output: Standard Output
Time Limit: 3 Seconds
Given n points on the XY plane, count how many regular rectangles are formed. A rectangle is regular if and only if its sides are all parallel to the axis.
Input
The first line contains the number of tests t(1<=t<=10). Each case contains a single line with a positive integer n(1<=n<=5000), the number of points. There are n lines follow, each line contains 2 integers x, y (0<=x, y<=109) indicating the coordinates of a point.
Output
For each test case, print the case number and a single integer, the number of regular rectangles found.
Sample Input Output for Sample Input
2 5 0 0 2 0 0 2 2 2 1 1 3 0 0 0 30 0 900 | Case 1: 1 Case 2: 0 |
Problemsetter: Rujia Liu, Member of Elite Problemsetters' Panel
Special Thanks: IOI2003 China National Training Team
思路:首先将x坐标和y坐标离散化一下....然后就开始直接乱搞了...有人n^2枚举对角线就可以了。 我的麻烦一些咯。
代码:
#include <iostream>
#include <vector>
#include <algorithm>
#include <string.h>
#include <cstring>
#include <map>
#include <set>
#include <stdio.h>
#include <cmath>
#include <cassert>
#include <math.h>
#define rep(i,a,b) for(int i=(a);i<(b);++i)
#define rrep(i,b,a) for(int i = (b); i >= (a); --i)
#define clr(a,x) memset(a,(x),sizeof(a))
#define LL long long
#define eps 1e-9
#define mp make_pair
using namespace std;
const int maxn = 5000 + 5;
int n;
struct Point
{
int x,y;
bool operator < (const Point & pt) const
{
if (x != pt.x) return x < pt.x;
return y < pt.y;
}
}pt[maxn];
bool vis[maxn][maxn];
vector<int> line[maxn];
void input()
{
scanf("%d",&n);
rep(i,0,n) scanf("%d%d",&pt[i].x,&pt[i].y);
sort(pt,pt+n);
vector<int> v;
rep(i,0,n) {
v.push_back(pt[i].x);
}
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
rep(i,0,n) {
pt[i].x = lower_bound(v.begin(),v.end(),pt[i].x) - v.begin();
}
v.clear();
rep(i,0,n) v.push_back(pt[i].y);
sort(v.begin(),v.end()); v.erase(unique(v.begin(),v.end()),v.end());
rep(i,0,n) pt[i].y = lower_bound(v.begin(),v.end(),pt[i].y) - v.begin();
rep(i,0,n) vis[pt[i].x][pt[i].y] = true;
rep(i,0,n+1) line[i].clear();
rep(i,0,n) line[pt[i].x].push_back(i);
}
bool visy[maxn];
vector<int> vx[maxn];
void solve()
{
int sz = 0;
clr(visy,0);
rep(i,0,maxn) vx[i].clear();
rep(i,0,n) {
if (line[i].empty()) break;
sz++;
}
vector<int> * v;
int ans = 0;
int a,y1,b,y2;
rrep(w,sz-1,0) {
rep(i,0,line[w].size()) {
a = line[w][i];
y1 = pt[a].y;
if (!visy[y1]) continue;
rep(j,i+1,line[w].size()) {
b = line[w][j];
y2 = pt[b].y;
if (!visy[y2]) continue;
if (vx[y1].size() < vx[y2].size()) v = &vx[y1];
else v = &vx[y2];
for(auto it = v->begin(); it != v->end(); ++it) {
if (vis[*it][y1] && vis[*it][y2]) ++ans;
}
}
}
rep(i,0,line[w].size()) {
int y = pt[line[w][i]].y;
vx[y].push_back(w);
visy[y] = true;
}
}
printf("%d\n",ans);
rep(i,0,n) {
int x = pt[i].x, y = pt[i].y;
vis[x][y] = false;
}
}
void Getinput()
{
freopen("in.txt","w",stdout);
int T = 1;
printf("%d\n",T);
while (T--) {
int n = 5000;
printf("%d\n",n);
rep(i,0,n/2) printf("%d %d\n",0,i);
rep(i,0,n-n/2) printf("1 %d\n",i);
}
}
int main()
{
//Getinput(); return 0;
#ifdef ACM
freopen("in.txt", "r", stdin);
// freopen("out.txt","w",stdout);
#endif // ACM
int T; cin >> T;
rep(cas,1,T+1) {
input();
printf("Case %d: ",cas);
solve();
}
}