您的位置:首页 > 其它

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)

这是用树状数组做的
// 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  delete system c