Time Limit: 1000MS Memory Limit: 65536K

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 ~ n 的城市,右边一排 1 ~ m 的城市,都从上到下依次对应。接着给你一些城市对,表示城市这两个城市相连;

最后问你一共有多少个交叉,其中处于城市处的交叉不算,并且每个位置最多只能有一个交叉。

题解:

抽象来说就是求逆序对的问题,虽然放在树状数组的章节里,但不一定要用树状数组,归并排序也可以……

还有关于k的范围……起点最多1000个,终点最多1000个,那么连线最多显然是1000*1000个啊……哪里坑了……

#include<cstdio>
#include<algorithm>
#define MAX 1000*1000+3
using namespace std;
struct Road{
int u,v;
}road[MAX],tmp[MAX];
int n,m,k;
long long cnt;
bool cmp(Road a,Road b)
{
if(a.u==b.u) return a.v<b.v;
else return a.u<b.u;
}
void Merge(int l,int m,int r)
{
int i = l;
int j = m + ;
int k = l;
while(i <= m && j <= r)
{
if(road[i].v > road[j].v)
{
tmp[k++] = road[j++];
cnt += m - i + ;
}
else
{
tmp[k++] = road[i++];
}
}
while(i <= m) tmp[k++] = road[i++];
while(j <= r) tmp[k++] = road[j++];
for(int i=l;i<=r;i++) road[i] = tmp[i];
}
void Merge_sort(int l,int r)
{
if(l < r)
{
int m = (l + r) >> ;
Merge_sort(l,m);
Merge_sort(m+,r);
Merge(l,m,r);
}
}
int main()
{
int t;
scanf("%d",&t);
for(int kase=;kase<=t;kase++)
{
scanf("%d%d%d",&n,&m,&k);
for(int i=;i<=k;i++) scanf("%d%d",&road[i].u,&road[i].v);
sort(road+,road+k+,cmp);
cnt=;
Merge_sort(,k);
printf("Test case %d: %I64d\n",kase,cnt);
}
}

不过既然是在BIT这节里的题,那总归也要用BIT做一下……

 #include<cstdio>
#include<algorithm>
#define MAXN 1000*1000+3
using namespace std;
int n,m,k;
struct Road{
int u,v;
}road[MAXN];
bool cmp(Road a,Road b)
{
if(a.u==b.u) return a.v<b.v;
else return a.u<b.u;
}
//BIT - 单点增加,区间查询 - st
struct _BIT{
int N,C[MAXN];
int lowbit(int x){return x&(-x);}
void init(int n)//初始化共有n个点
{
N=n;
for(int i=;i<=N;i++) C[i]=;
}
void add(int pos,int val)//在pos点加上val
{
while(pos<=N)
{
C[pos]+=val;
pos+=lowbit(pos);
}
}
int sum(int pos)//查询1~pos点的和
{
int ret=;
while(pos>)
{
ret+=C[pos];
pos-=lowbit(pos);
}
return ret;
}
}BIT;
//BIT - 单点增加,区间查询 - ed
int main()
{
int t;
scanf("%d",&t);
for(int kase=;kase<=t;kase++)
{
scanf("%d%d%d",&n,&m,&k);
for(int i=;i<=k;i++) scanf("%d%d",&road[i].u,&road[i].v);
sort(road+,road+k+,cmp); long long cnt=;
BIT.init(m);
for(int i=;i<=k;i++)
{
BIT.add(road[i].v,);//road[i].v出现一次,加上
cnt+=BIT.sum(m)-BIT.sum(road[i].v);//计算出在目前情况下,有多少个比road[i].v大的数出现过
}
printf("Test case %d: %I64d\n",kase,cnt);
}
}


当然啦,事实告诉了我们,用BIT不是没有道理的,各方面都比归并排序求逆序对要好一些。

更多树状数组模板请走传送门:树状数组进阶

POJ 3067 - Japan - [归并排序/树状数组(BIT)求逆序对]的更多相关文章

  1. POJ 3067 Japan 【树状数组经典】

    题目链接:POJ 3067 Japan Japan Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 32076   Accep ...

  2. poj 3067 Japan(树状数组求逆序数)

    链接:http://poj.org/problem?id=3067 题意:左边有n个城市,右边有m个城市,建k条道路,问有这k条道路中有多少个交点. 分析:将城市按x和y从小到大排序,对于每条道路,求 ...

  3. POJ 3067 Japan(树状数组)

                                                                                  Japan   Time Limit: 10 ...

  4. poj 3067 Japan 【树状数组】

    <题目链接> 题目大意: 有两个点集,这两个点集从上至下分别从1~n,1~m编号,现在给出n组数据,(x,y),表示左边点集编号为x的点与右边点集编号为y的点相连,现在要求计算这些线段的交 ...

  5. POJ 3067 Japan 【 树状数组 】

    题意:左边有n个城市,右边有m个城市,现在修k条路,问会形成多少个交点 先按照x从小到大排,x相同的话,则按照y从小到大排,然后对于每一个y统计前面有多少个y比它大,它们就一定会相交 另外要用long ...

  6. POJ 2299 树状数组+离散化求逆序对

    给出一个序列 相邻的两个数可以进行交换 问最少交换多少次可以让他变成递增序列 每个数都是独一无二的 其实就是问冒泡往后 最多多少次 但是按普通冒泡记录次数一定会超时 冒泡记录次数的本质是每个数的逆序数 ...

  7. POJ 2299 Ultra-QuickSort (树状数组+离散化 求逆序数)

    In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a seque ...

  8. HDU 1394 树状数组+离散化求逆序数

    对于求逆序数问题,学会去利用树状数组进行转换求解方式,是很必要的. 一般来说我们求解逆序数,是在给定一串序列里,用循环的方式找到每一个数之前有多少个比它大的数,算法的时间复杂度为o(n2). 那么我们 ...

  9. POJ 3067 原来是树状数组--真的涨姿势

    题意:计划在东边的城市和西边的城市中建路,东边的点从1.....n,西边的点从1......m,求这些点连起来后有多少个交叉. PS:这个题目没有任何思路,没想到是树状数组.... 交叉出5个点 分析 ...

随机推荐

  1. linux修改文件所属用户和用户组

    使用chown命令可以修改文件或目录所属的用户:       命令:chown 用户 目录或文件名       例如:chown testAdmin /home/work  (把home目录下的xua ...

  2. 执行RF设置顶级测试套件的名称

    场景1:通过pybot进行单个output文件情况下设置 -N --name name 设置顶级测试套件的名称.名称中的下划线将转换为空格. 默认名称为执行的数据源的名称. 场景2:通过rebot进行 ...

  3. U3D 游戏引擎之游戏架构脚本该如何来写

    这篇文章MOMO主要想大家说明一下我在Unity3D游戏开发中是如何写游戏脚本的,对于Unity3D这套游戏引擎来说入门极快,可是要想做好却非常的难.这篇文章的目的是让哪些已经上手Unity3D游戏引 ...

  4. linux 设置分辨率(转)

    linux 设置分辨率 如果你需要在linux上设置显示屏的分辨率,分两种情况:分辨率模式存在与分辨率模式不存在,具体如下. 1,分辨率模式已存在 1)如何查询是否存在: 图形界面:在System S ...

  5. javascript实现的网页打印

    打印全部页面: <body onload="javascript:window.print()"> 实现局部打印,可以将不参加打印的元素设置“display=none” ...

  6. 【转】java文件操作大全

    一.获得控制台用户输入的信息 public String getInputMessage() throws IOException...{         System.out.println(&qu ...

  7. __declspec(dllimport)与__declspec(dllexport)作用总结

    参考自:http://bbs.csdn.net/topics/330169671 __declspec(dllexport):导出符号,也就是定义需要导出函数的dll中给导出函数的函数声明前面加上导出 ...

  8. codeforces水题100道 第十一题 Codeforces Round #143 (Div. 2) A. Team (brute force)

    题目链接:http://www.codeforces.com/problemset/problem/231/A题意:问n道题目当中有多少道题目是至少两个人会的.C++代码: #include < ...

  9. codeforces水题100道 第五题 Codeforces Round #304 (Div. 2) A. Soldier and Bananas (math)

    题目链接:http://www.codeforces.com/problemset/problem/546/A题意:一个人现在有n元,它买第i根香蕉需要i*k元,问他要买w根香蕉的话,需要问他的朋友借 ...

  10. Lua中的table构造式(table constructor)

    最简单的构造式就是一个空构造式{},用于创建一个空table. 构造式还可以用于初始化数组.例如,以下语句:days = {"Sunday", "Monday" ...