【原】 POJ 3067 Japan 2D树状数组+逆序数 解题报告
http://poj.org/problem?id=3067
方法:
求交点个数,我们可以将其转化为求逆序数问题。
两线段(x1,y1)、(x2,y2)相交当且仅当(x1-x2)*(y1-y2)<0
对所有输入线段按x排序,对同x的线段按y排序。利用排序后的输入计算逆序数。
数组元素a[i]记录y为i的线段的个数。依次读入排序后的线段,每取一个y值,++a[y],并计算
区间和a[y+1...M]即为与此线段相交的线段数。
因为每次读取的线段的x值都比之前的x要大,如果与之前的某些线段相交,那么y值一定要比那些
线段的小。所以每读入一条线段就计算比其y大的线段数,即区间和a[y+1...M]
复杂度:O(k*logk)+O(k*logM)
注意:
逆序数为n^2级别的,所以需要__int64
Description
Japan plans to welcome the ACM ICPC World Finals and a lot of roads must be built for the venue. Japan is tall island with N cities on the East coast and M cities on the West coast (M <= 1000, N <= 1000). K superhighways will be build. Cities on each coast are numbered 1, 2, ... from North to South. Each superhighway is straight line and connects city on the East coast with city of the West coast. The funding for the construction is guaranteed by ACM. A major portion of the sum is determined by the number of crossings between superhighways. At most two superhighways cross at one location. Write a program that calculates the number of the crossings between superhighways.
Input
The input file starts with T - the number of test cases. Each test case starts with three numbers – N, M, K. Each of the next K lines contains two numbers – the numbers of cities connected by the superhighway. The first one is the number of the city on the East coast and second one is the number of the city of the West coast.
Output
For each test case write one line on the standard output:
Test case (case number): (number of crossings)
Sample Input
1
3 4 4
1 4
2 3
3 2
3 1
Sample Output
Test case 1: 5
1: #include <stdio.h>
2: #include <iostream>
3: #include <algorithm> //sort
4:
5: using namespace std ;
6:
7: const int N = 1001 ;
8:
9: __int64 tree[N] ;
10:
11: struct xy
12: {
13: int x ; int y ;
14: };
15:
16: xy input[N*N+50] ;
17:
18: __int64 GetSum( int idx )
19: {
20: __int64 sum = 0 ;
21: while( idx>0 )
22: {
23: sum += tree[idx] ;
24: idx -= ( idx & -idx ) ;
25: }
26: return sum ;
27: }
28:
29: void AddVal( int n, int idx, __int64 val )
30: {
31: while( idx<=n )
32: {
33: tree[idx] += val ;
34: idx += ( idx & -idx ) ;
35: }
36: }
37:
38: bool cmp( const xy& a, const xy& b )
39: {
40: if( a.x < b.x )
41: return true ;
42: else if( a.x == b.x )
43: return a.y<=b.y ;
44: else
45: return false ;
46: }
47:
48: void run3067()
49: {
50: int c ;
51: int n,m,k ;
52: int x,y ;
53: int i,j ;
54: int total ;
55: __int64 inverse ;
56:
57: scanf( "%d", &c ) ;
58: for( i=1 ; i<=c ; ++i )
59: {
60: scanf( "%d%d%d", &n,&m,&k ) ;
61:
62: memset( tree, 0, (m+1)*sizeof(__int64) ) ;
63:
64: for( j=0 ; j<k ; ++j )
65: {
66: scanf( "%d%d", &x,&y );
67: input[j].x = x ;
68: input[j].y = y ;
69: }
70:
71: sort( input , input+k , cmp ) ;
72:
73: inverse = 0 ;
74: total = 0 ;
75:
76: for( j=0 ; j<k ; ++j )
77: {
78: y = input[j].y ;
79:
80: AddVal( m, y, 1 ) ;
81: ++total ;
82: inverse += ( total - GetSum(y) ) ;
83: }
84:
85: printf("Test case %d: %I64d\n", i,inverse) ;
86: }
87: }