1. 程式人生 > >POJ-3067 Japan---樹狀數組逆序對變形

POJ-3067 Japan---樹狀數組逆序對變形

AR for nbsp inf sizeof ring void str bsp

題目鏈接:

https://vjudge.net/problem/POJ-3067

題目大意:

日本島東海岸與西海岸分別有N和M個城市,現在修高速公路連接東西海岸的城市,求交點個數。

解題思路:

記每條告訴公路為(x,y), 即東岸的第x個城市與西岸的第y個城市修一條路。當兩條路有交點時,滿足(x1-x2)*(y1-y2) < 0。所以,將每條路按x從小到達排序,若x相同,按y從小到大排序。 然後按排序後的公路用樹狀數組在線更新,求y的逆序數之和 即為交點個數。

比如樣例

1 4
2 3
3 2
3 1

排完序後

1 4
2 3
3 1
3 2

1、加入1 4,此時比4大的元素為0,交點數目為0

技術分享圖片

2、加入2 3,此時比3大的元素數目為1,交點數目為1

技術分享圖片

3、加入3 1,此時比1大的數字有兩個,交點數目為3

技術分享圖片

4、加入3 2,此時比2大的數字有2個,交點數目為5

技術分享圖片

如果先加人3 2,再加入3 1的話會導致3 1這條計算交點的時候吧3 2算進去,但實際上並沒有交點,所以排序順序在x相同的y從小到大排序

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<string>
 5 #include<map>
 6 #include<set>
 7 #include<cmath>
 8
#include<algorithm> 9 using namespace std; 10 typedef long long ll; 11 const int maxn = 1000000 + 10; 12 int n, m, T, k, cases; 13 struct node 14 { 15 int x, y; 16 bool operator <(const node& a)const 17 { 18 return x < a.x || x == a.x && y < a.y; 19 } 20 };
21 node a[maxn]; 22 int tree[10000]; 23 int lowbit(int x) 24 { 25 return x & (-x); 26 } 27 ll sum(int x) 28 { 29 ll ans = 0; 30 while(x) 31 { 32 ans += tree[x]; 33 x -= lowbit(x); 34 } 35 return ans; 36 } 37 void add(int x, int d) 38 { 39 while(x <= m) 40 { 41 tree[x] += d; 42 x += lowbit(x); 43 } 44 } 45 int main() 46 { 47 cin >> T; 48 while(T--) 49 { 50 cin >> n >> m >> k; 51 memset(tree, 0, sizeof(tree)); 52 for(int i = 1; i <= k; i++) 53 { 54 scanf("%d%d", &a[i].x, &a[i].y); 55 } 56 sort(a + 1, a + 1 + k); 57 ll ans = 0; 58 for(ll i = 1; i <= k; i++) 59 { 60 add(a[i].y, 1); 61 ans += (i - sum(a[i].y)); 62 } 63 printf("Test case %d: %lld\n", ++cases, ans); 64 } 65 return 0; 66 }

POJ-3067 Japan---樹狀數組逆序對變形