思路:
树状数组 + 扫描线。
实现:
1 #include <cstdio> 2 #include <vector> 3 #include <algorithm> 4 using namespace std; 5 const int MAXN = 100005; 6 int x[MAXN], y[MAXN], bit[MAXN], cnt[MAXN], now[MAXN], n; 7 bool vis[MAXN]; 8 vector<int> lines[MAXN]; 9 int lowbit(int x) { return x & -x; } 10 void add(int i, int x) 11 { 12 while (i <= MAXN) { bit[i] += x; i += lowbit(i); } 13 } 14 int sum(int i) 15 { 16 int ans = 0; 17 while (i) { ans += bit[i]; i -= lowbit(i); } 18 return ans; 19 } 20 int compress(int * a) 21 { 22 vector<int> v(a, a + n); 23 sort(v.begin(), v.end()); 24 v.erase(unique(v.begin(), v.end()), v.end()); 25 for (int i = 0; i < n; i++) a[i] = lower_bound(v.begin(), v.end(), a[i]) - v.begin() + 1; 26 return v.size(); 27 } 28 int main() 29 { 30 scanf("%d", &n); 31 for (int i = 0; i < n; i++) scanf("%d %d", x + i, y + i); 32 int X = compress(x), Y = compress(y); 33 for (int i = 0; i < n; i++) { lines[x[i]].push_back(y[i]); cnt[y[i]]++; } 34 int ans = 0; 35 for (int i = 1; i <= X; i++) 36 { 37 sort(lines[i].begin(), lines[i].end()); 38 for (int j = 0; j < lines[i].size() - 1; j++) ans += sum(lines[i][j + 1] - 1) - sum(lines[i][j]); 39 for (int j = 0; j < lines[i].size(); j++) 40 { 41 int tmp = lines[i][j]; 42 if (!vis[tmp]) { vis[tmp] = true; add(tmp, 1); } 43 now[tmp]++; 44 if (now[tmp] == cnt[tmp]) add(tmp, -1); 45 } 46 } 47 printf("%d\n", ans + n); 48 return 0; 49 }