POJ 3067 Japan
2014-07-20 22:23
302 查看
题目大意:
东海岸和西海岸各有N和M个城市(N, M ≤ 1000),两边的城市分别按照从北到南顺序编号成1 ~ N和1 ~ M,现有K条高速路连接着东西海岸的城市,每条高速路直通两个城市并且是直线的(非弯曲的),现要你统计高速路之间总共有多少个交点,如果在起点或终点相交的不算交点!!
现有T个测例,每个测例中给出N、M和K,接下来给出K条高速路的连接的两个城市的编号,第一个为东海岸的城市,第二个为西海岸的城市,对于每个测例要求输出交点个数。
题目链接
注释代码:
portion:n, 部分
fund:n, 基金,资金
superhighway:n, 超级高速公路
coast:n, 海岸
venue:n, 举办场所,犯罪地点,审判地
东海岸和西海岸各有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, 举办场所,犯罪地点,审判地
相关文章推荐
- poj-3067-Japan(树状数组)
- POJ 3067 Japan
- POJ 3067 Japan(树状数组)
- POJ 3067 Japan
- POJ 3067 Japan(树状数组)
- POJ 3067 Japan(树状数组:求逆序)
- poj 3067 japan 树状数组
- POJ 3067 Japan(树状数组:求逆序)
- POJ 3067 Japan 线段树
- poj 3067 Japan 二维树状数组(入门)
- POJ 3067 Japan (树状数组)
- poj 3067 Japan(树状数组求逆序数)
- POJ 3067 Japan(树状数组求逆序对个数)
- POJ 3067 Japan 【 树状数组 】
- POJ 3067 Japan
- POJ 3067 Japan(经典树状数组)
- POJ 3067 japan
- 两边点连直线求交点总数 树状数组或线段树 poj 3067 Japan
- poj 3067 Japan(逆序数)
- poj - 3067 - Japan(树状数组)