F - Must Be Rectangular!


Time Limit: 2 sec / Memory Limit: 1024 MB

Score : 600600 points

Problem Statement

There are NN dots in a two-dimensional plane. The coordinates of the ii-th dot are (xi,yi)(xi,yi).

We will repeat the following operation as long as possible:

  • Choose four integers aa, bb, cc, dd (a≠c,b≠d)(a≠c,b≠d) such that there are dots at exactly three of the positions (a,b)(a,b), (a,d)(a,d), (c,b)(c,b) and (c,d)(c,d), and add a dot at the remaining position.

We can prove that we can only do this operation a finite number of times. Find the maximum number of times we can do the operation.

Constraints

  • 1≤N≤1051≤N≤105
  • 1≤xi,yi≤1051≤xi,yi≤105
  • If i≠ji≠j, xi≠xjxi≠xj or yi≠yjyi≠yj.
  • All values in input are integers.

Input

Input is given from Standard Input in the following format:

NN
x1x1 y1y1
::
xNxN yNyN

Output

Print the maximum number of times we can do the operation.


Sample Input 1 Copy

Copy

3
1 1
5 1
5 5

Sample Output 1 Copy

Copy

1

By choosing a=1a=1, b=1b=1, c=5c=5, d=5d=5, we can add a dot at (1,5)(1,5). We cannot do the operation any more, so the maximum number of operations is 11.


Sample Input 2 Copy

Copy

2
10 10
20 20

Sample Output 2 Copy

Copy

0

There are only two dots, so we cannot do the operation at all.


Sample Input 3 Copy

Copy

9
1 1
2 1
3 1
4 1
5 1
1 2
1 3
1 4
1 5

Sample Output 3 Copy

Copy

16

We can do the operation for all choices of the form a=1a=1, b=1b=1, c=ic=i, d=jd=j (2≤i,j≤5)(2≤i,j≤5), and no more. Thus, the maximum number of operations is 1616.

题意:

给你n个点,如果有三个点如下图红点所示,则蓝色的就是可以扩充的点,问有多少个这样的点。

Atcoder ABC F - Must Be Rectangular!_#define

分析:

下图来自

Atcoder ABC F - Must Be Rectangular!_ci_02

我们发现这个连通区域内的点数就是平行与x线条个数乘以平行与y线条个数,如果我们求出来这个,则减去已有的即可。

首先,连通区域的定义是x坐标与y坐标任意一点在这个集合内,这时候可以用并查集,但我们又不能完全的混合在一起,因为最后需要x的线条乘以y的线条个数,所以规定x在0~N,y在N+1~2*N(N为坐标最大值)

举一个例子,

N=4

(2,1)(1,1) (1,2)

则x坐标 1 2 3 4   y:5  6 7 8

       fa     1 2 3 4       5  6 7 8

1.

添加(2,1)fa[find(x)]=find(y+N) fa[2]=5

x坐标 1 2 3 4   y:5  6 7 8

  fa     1 5 3 4          5 6 7 8

2.

添加(1,1)fa[find(x)]=find(y+N) fa[1]=5

x坐标 1 2 3 4    y:5  6 7 8

  fa     5 5 3 4          5 6 7 8

3.

添加(1,2)fa[find(x)]=find(y+N) fa[5]=6

x坐标 1 2 3 4   y:5  6 7 8

6

 

 

#include<bits/stdc++.h>
using namespace std;
#define N 4
typedef long long ll;
int n,f[N<<1];
int getf(int x)
{
return x==f[x]?x:f[x]=getf(f[x]);
}
int sz1[N<<1],sz2[N<<1];
int out()
{
for(int i=1;i<=2*N;i++)
cout<<f[i]<<" ";
cout<<endl;
}
int main()
{
ll ans=0;
cin>>n;
for(int i=1; i<=N+N; ++i)
f[i]=i;
int u,v;
for(int i=1; i<=n; ++i)
{
cin>>u>>v;
f[getf(u)]=getf(v+N);
// out();
}

for(int i=1; i<=N; ++i)
sz1[getf(i)]+=1;
for(int i=N+1; i<N+N; ++i)
sz2[getf(i)]+=1;
for(int i=1; i<N+N; ++i)
ans+=1ll*sz1[i]*sz2[i];
cout<<ans-n<<endl;
return 0;
}
from queue import PriorityQueue
import sys

sys.setrecursionlimit(10**9)

IA = lambda: [int(x) for x in input().split()]
IM = lambda N: [IA() for _ in range(N)]
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
N=100005
fa=[int(0) for i in range(2*(N+1))]
xNum=[int(0) for i in range(2*(N+1))]
yNum=[int(0) for i in range(2*(N+1))]

def find(x):
if(x==fa[x]):return x
else:
fa[x]=find(fa[x])
return fa[x]

n=input()
n=int(n)

for i in range(2*N+1):
fa[i]=i

for i in range(n):
x,y=IA()
y+=N
fx=int(find(x))
fy=int(find(y))

if(fx!=fy):
fa[fy]=fx
for i in range(N):
xNum[find(i)]+=1
for i in range(N):
yNum[find(i+N)]+=1
ans=0
for i in range(N):
ans+=xNum[i]*yNum[i]
print(ans-n)