3067 Japan( 树状数组 || 归并排序 )
2011-06-19 22:40
197 查看
题意 : 日本的东西海岸各有N, M个城市,它们之间有K条路,求这K条路的交点个数( N,M <= 1000 )
先用树状数组做了一下,时间480ms, 内存2M; 又用归并排序,稍慢一点,时间590ms, 内存5M
这也正常,用树状数组的时间复杂度O(KlgN), 归并O(KlgK), 其中(N<=1000, K <= 1000000)
这是用树状数组做的
下面是归并排序做的
先用树状数组做了一下,时间480ms, 内存2M; 又用归并排序,稍慢一点,时间590ms, 内存5M
这也正常,用树状数组的时间复杂度O(KlgN), 归并O(KlgK), 其中(N<=1000, K <= 1000000)
这是用树状数组做的
// 3067 Japan.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <iostream> #include <algorithm> using namespace std; const int Max = 1000; // 对象 int M, N, K; struct Road { int b, e; }road[Max*Max]; long long C[Max+1]; // 树状数组 //函数 bool greater( const Road & r1, const Road & r2 ) { if( r1.b < r2.b ) return true; else if( r1.b == r2.b ) return r1.e < r2.e; else return false; } //-----------------树状数组操作------------------// int TreeScope( const int x ) { return ( x ^ (x - 1) ) & x; } void Update( int x ) { while( x <= N ) { C[x] += 1; x += TreeScope( x ); // 得到父节点 } } int GetSum( int x ) { int sum = 0; while( x > 0 ) { sum += C[x]; x -= TreeScope( x ); // 得到兄弟节点 } return sum; } //-----------------------------------------------// int main() { int T; cin >> T; for( int t = 1; t <= T; ++ t ) { memset( C, 0, sizeof(C) ); scanf( "%d%d%d", & M, & N, & K ); for( int i = 0; i < K; ++ i ) scanf( "%d%d", & road[i].b, & road[i].e ); sort( road, road + K, greater ); // 统计逆序数 long long res = 0; for( int i = 0; i < K; ++ i ) { Update( road[i].e ); int s = GetSum( road[i].e ); res += ( i+1 ) - s; // 逆序数[i] = 总线段数 - 正序数[i] } printf( "Test case %d: %lld/n", t, res ); } system( "pause" ); return 0; }
下面是归并排序做的
// 3067 Japan(归并排序求逆序数).cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <iostream> #include <algorithm> using namespace std; const int Max = 1000; // 对象 int N, M, K; struct Road { int b, e; }road[Max*Max]; int A[Max*Max]; // 终点集合 int a1[Max*Max], a2[Max*Max]; long long res; // 逆序数 <- 0 // 函数 bool greater( const Road & r1, const Road & r2 ) { if( r1.b < r2.b ) return true; else if( r1.b == r2.b ) return r1.e < r2.e; else return false; } void Marge( const int l, const int mid, const int r ) { int len1 = mid - l + 1; int len2 = r - mid; /*int* a1 = new int[len1]; int* a2 = new int[len2];*/ memcpy( a1, A + l, len1*sizeof(int) ); memcpy( a2, A + mid + 1, len2*sizeof(int) ); // 归并 int p1 = 0, p2 = 0; while( p1 < len1 && p2 < len2 ) if( a1[p1] <= a2[p2] ) A[ l+p1+p2 ] = a1[ p1++ ]; else { A[ l+p1+p2 ] = a2[ p2++ ]; res += len1 - p1; } // 合并剩余的 while( p1 < len1 ) A[ l+p1+p2 ] = a1[ p1++ ]; while( p2 < len2 ) A[ l+p1+p2 ] = a2[ p2++ ]; /*delete [] a1; delete [] a2;*/ } void MargeSort( const int l, const int r ) { if( l == r ) return; int mid = ( l + r ) >> 1; ::MargeSort( l, mid ); ::MargeSort( mid + 1, r ); ::Marge( l, mid, r ); } int main() { int T; cin >> T; for( int t = 1; t <= T; ++ t ) { scanf( "%d%d%d", & M, & N, & K ); for( int i = 0; i < K; ++ i ) scanf( "%d%d", & road[i].b, & road[i].e ); if( K == 0 ) { printf( "Test case %d: 0/n", t ); continue; } sort( road, road + K, greater ); for( int i = 0; i < K; ++ i ) A[i] = road[i].e; // 统计逆序数 res = 0; ::MargeSort( 0, K - 1 ); printf( "Test case %d: %lld/n", t, res ); } system( "pause" ); return 0; }
相关文章推荐
- POJ 3067 Japan(树状数组求逆序对)
- Poj 3067 Japan【树状数组】
- POJ 3067 Japan 树状数组求逆序对
- POJ 3067—— Japan(树状数组)
- POJ 3067 Japan(树状数组)
- POJ 3067 Japan 【树状数组 向下更新 向上求和】
- POJ 3067 Japan(树状数组求逆序数)
- POJ 3067 Japan(树状数组:求逆序)
- Japan - POJ 3067 排序+树状数组
- POJ 3067 Japan(经典树状数组)
- POJ 3067 Japan(树状数组)
- poj 3067 Japan(树状数组)
- pku 3067 Japan 树状数组求逆序数
- poj 3067 - Japan(树状数组)
- 3067 Japan 树状数组
- poj 3067 Japan(树状数组)
- poj 3067 Japan(树状数组求逆序数)
- poj-3067-Japan(树状数组)
- poj 3067 树状数组 Japan
- POJ 3067 Japan (树状数组)