1. Abridged Problem Statement  
Given K black cells on an infinite grid (all other cells are white), you repeatedly “complete” any axis-aligned rectangle whenever three of its corners are black and the fourth is white—turning that fourth corner black. When no more moves are possible, how many black cells remain?

2. Detailed Editorial  
**Key Observation.** Once you can fill in a rectangle corner, you’ll eventually fill all “missing” cells in any connected block of rows and columns that are linked by the initial black cells. Formally:  
- Think of each black cell as a point (x, y).  
- Build a graph whose vertices are these points; connect two points if they share the same x (same row) or the same y (same column).  
- In each connected component of this graph, let R be the number of *distinct* x-coordinates and C be the number of *distinct* y-coordinates present.  
- You can show that the rectangle-filling process will eventually paint every cell in the Cartesian product R×C—i.e. R·C black cells in that component.  

Hence the final answer is the sum over all components of (number of distinct rows) × (number of distinct columns).

Implementation Steps:  
1. Read the K points into arrays x[i], y[i].  
2. While reading, maintain two maps: one from x-coordinate to the index of the *last* point seen with that x, and similarly for y. Whenever you read a new point i, if you’ve seen that x before at index j, add an undirected edge i–j; likewise for y. This chains all points in a given row (or column) into a single connected component.  
3. Run a DFS/BFS over the graph’s K vertices. For each component, collect its distinct x’s and y’s in two sets; when the DFS finishes, add |rows|×|cols| to your answer.  
4. Print the accumulated sum.

Time Complexity: O(K log K) from the maps (or O(K) if you precompress coordinates), plus O(K) for the graph traversal.

3. Provided C++ Solution with Detailed Comments  
```cpp
#include <bits/stdc++.h>
using namespace std;

static const int MAXN = 1 << 20;  // upper bound on K (we over-allocate)

int n;                           // number of initial black cells
vector<int> adj[MAXN];           // adjacency list for the graph of points
bool used[MAXN];                 // marks visited points in DFS
map<int,int> row_last, col_last;// map coordinate → last point index seen
int x[MAXN], y[MAXN];            // coordinates of each point

// Read input and build adjacency based on shared rows or columns
void read() {
    cin >> n;
    for(int i = 0; i < n; i++) {
        cin >> x[i] >> y[i];

        // If we've seen this y-coordinate before, connect i to that point
        auto itc = col_last.find(y[i]);
        if(itc != col_last.end()) {
            int j = itc->second;
            adj[i].push_back(j);
            adj[j].push_back(i);
        } else {
            col_last[y[i]] = i;
        }

        // Similarly for x-coordinate (rows)
        auto itr = row_last.find(x[i]);
        if(itr != row_last.end()) {
            int j = itr->second;
            adj[i].push_back(j);
            adj[j].push_back(i);
        } else {
            row_last[x[i]] = i;
        }
    }
}

set<int> rows, cols;  // will collect distinct x’s and y’s in a component

// DFS from point u: marks all reachable points and records their x/y
void dfs(int u) {
    used[u] = true;
    rows.insert(x[u]);
    cols.insert(y[u]);
    for(int v : adj[u]) {
        if(!used[v]) {
            dfs(v);
        }
    }
}

void solve() {
    long long answer = 0;
    // For each unvisited point, run a DFS to find its component
    for(int i = 0; i < n; i++) {
        if(!used[i]) {
            rows.clear();
            cols.clear();
            dfs(i);
            // In this component, we can fill all rows×cols cells
            answer += (long long)rows.size() * (long long)cols.size();
        }
    }
    cout << answer << '\n';
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    read();
    solve();
    return 0;
}
```

4. Python Solution with Detailed Comments  
```python
import sys
sys.setrecursionlimit(10**7)
input = sys.stdin.readline

def main():
    K = int(input())
    xs = [0]*K
    ys = [0]*K
    # Map each x (resp. y) to the list of point indices having that coordinate
    map_x = {}
    map_y = {}

    for i in range(K):
        xi, yi = map(int, input().split())
        xs[i] = xi
        ys[i] = yi
        map_x.setdefault(xi, []).append(i)
        map_y.setdefault(yi, []).append(i)

    visited = [False]*K
    answer = 0

    # BFS/DFS will consume each group once; after exploring all points
    # on some x or y, we clear its list to avoid revisiting.
    from collections import deque
    for i in range(K):
        if not visited[i]:
            queue = deque([i])
            visited[i] = True
            comp_rows = set()
            comp_cols = set()

            while queue:
                u = queue.popleft()
                rx, ry = xs[u], ys[u]
                comp_rows.add(rx)
                comp_cols.add(ry)

                # Explore all other points sharing the same x
                for v in map_x.get(rx, []):
                    if not visited[v]:
                        visited[v] = True
                        queue.append(v)
                # Clear so we don't re-explore this row later
                map_x[rx] = []

                # Explore all other points sharing the same y
                for v in map_y.get(ry, []):
                    if not visited[v]:
                        visited[v] = True
                        queue.append(v)
                # Clear so we don't re-explore this column later
                map_y[ry] = []

            # This component can be filled to (#rows)×(#cols)
            answer += len(comp_rows) * len(comp_cols)

    print(answer)

if __name__ == "__main__":
    main()
```

5. Compressed Editorial  
Model the black cells as nodes in a graph, linking any two on the same row or column. In each connected component, if there are R distinct rows and C distinct columns, the rectangle-completion process fills all R × C positions. Sum R·C over components.