POJ 3067 Japan

题目大意:

        东海岸和西海岸各有N和M个城市(N, M ≤ 1000),两边的城市分别按照从北到南顺序编号成1 ~ N和1 ~ M,现有K条高速路连接着东西海岸的城市,每条高速路直通两个城市并且是直线的(非弯曲的),现要你统计高速路之间总共有多少个交点,如果在起点或终点相交的不算交点!!

        现有T个测例,每个测例中给出N、M和K,接下来给出K条高速路的连接的两个城市的编号,第一个为东海岸的城市,第二个为西海岸的城市,对于每个测例要求输出交点个数。

题目链接

注释代码:

/*                       
 * Problem ID : POJ 3067 Japan
 * Author     : Lirx.t.Una                       
 * Language   : C++           
 * Run Time   : 407 ms                       
 * Run Memory : 1456 KB                       
*/   

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>

//思路:
//如果两直线(a_lft, a_rht)和(b_lft, b_rht)相交的话
//必定满足(a_lft - b_lft)(a_rht - b_rht) < 0
//其中也包含了在起点或终点相交的情况(=0不在其中)
//因此可以将直线按照rht从小到大排序
//再依次检测每条直线,如果当前直线为(b_lft, b_rht)而之前的直线为(a_lft, b_rht)
//则如果a_rht != b_rht,则只要找出之前lft值大于b_lft的直线的个数即可
//但是如果a_rht == b_rht的话,就不能直接找之前lft值大于b_lft的直线的个数了,因为
  //在起终点相交不算交点,因此找到的都不算
  //但是如果排序时当rht相等时按照lft从小到大排序,那么即使a_rht和b_rht相等,a_lft也是
  //小于等于b_lft的的,因此就不会计入到大于b_lft的直线的数量当中

//因此解法为:先按照rht从小到大排序如果rht相等就按照lft从小到大排序,之后便得到了
//一个新的lft序列,最终的答案就是新的lft序列的逆序数

//一座海岸城市的最大数量
#define	MAXN		1000

using namespace std;

typedef	__int64		llg;

struct	Road {
	
	short	lft, rht;//表示东海岸城市和西海岸城市的编号
	
	bool
	operator<(const Road &oth)//排序
	const {
		
		if ( rht == oth.rht ) return lft < oth.lft;
		return rht < oth.rht;
	}
};

Road	rd[MAXN * MAXN];//保存告诉公路,最多有MAXN * MAXN条
int		c[MAXN + 1];//树状数组,最大元素可能为MAXN * MAXN因此用int型
//用于求逆序数

short	lowbit[MAXN + 1];

int		n;//东海岸城市个数

void
update(int x) {
	
	while ( x <= n ) {
		
		c[x]++;
		x += lowbit[x];
	}
}

llg
query(int x) {
	
	llg		sum;//可能超过int
	
	sum = 0;
	while ( x > 0 ) {
		
		sum += c[x];
		x   -= lowbit[x];
	}
	
	return sum;
}

int
main() {
	
	int		t, iscn;//测例数
	int		m, k;//东海岸城市数和高速公路条数
	
	int		i;//计数变量
	
	llg		ans;//最终交点个数
	
	for ( i = 1; i <= MAXN; i++ ) lowbit[i] = i & -i;//打表
	
	scanf("%d", &t);
	iscn = 0;
	
	while ( t-- ) {
		
		scanf("%d%d%d", &n, &m, &k);
		for ( i = 0; i < k; i++ )
			scanf("%d%d", &rd[i].lft, &rd[i].rht);
		sort(rd, rd + k);
		
		memset(c, 0, sizeof(c));
		
		ans = 0;
		for ( i = 0; i < k; i++ ) {//排序后得到lft序列
			//求lft序列的逆序数即可
			
			update( rd[i].lft );
			ans += i + 1 - query( rd[i].lft );
		}
		
		printf("Test case %d: %I64d\n", ++iscn, ans);
	}
	
	return 0;
}
无注释代码:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>

#define	MAXN		1000

using namespace std;

typedef	__int64		llg;

struct	Road {

	short	lft, rht;

	bool
	operator<(const Road &oth)
	const {
	
		if ( rht == oth.rht ) return lft < oth.lft;
		return rht < oth.rht;
	}
};

Road	rd[MAXN * MAXN];
int		c[MAXN + 1];

short	lowbit[MAXN + 1];

int		n;

void
update(int x) {

	while ( x <= n ) {
	
		c[x]++;
		x += lowbit[x];
	}
}

llg
query(int x) {

	llg		sum;

	sum = 0;
	while ( x > 0 ) {
	
		sum += c[x];
		x   -= lowbit[x];
	}

	return sum;
}

int
main() {

	int		t, iscn;
	int		m, k;

	int		i;

	llg		ans;

	for ( i = 1; i <= MAXN; i++ ) lowbit[i] = i & -i;

	scanf("%d", &t);
	iscn = 0;

	while ( t-- ) {
	
		scanf("%d%d%d", &n, &m, &k);
		for ( i = 0; i < k; i++ )
			scanf("%d%d", &rd[i].lft, &rd[i].rht);
		sort(rd, rd + k);

		memset(c, 0, sizeof(c));

		ans = 0;
		for ( i = 0; i < k; i++ ) {
		
			update( rd[i].lft );
			ans += i + 1 - query( rd[i].lft );
		}

		printf("Test case %d: %I64d\n", ++iscn, ans);
	}

	return 0;
}
单词解释:

portion:n, 部分

fund:n, 基金,资金

superhighway:n, 超级高速公路

coast:n, 海岸

venue:n, 举办场所,犯罪地点,审判地

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值