POJ 3067 Japan【一维树状数组】


POJ 3067 Japan


核心算法:一维树状数组
大意:Japan在东边有n座城市,从北到南编号依次为1,2,3...n
在西边有m座城市,从北到南编号分别为1,2,3...m
现要在南北城市之间修建k条超级高速公路,求会出现多少个十字路口
(注:每个十字路口只能由两条交叉的路所构成)
输入:T   .....cases数
     n,m,k
  以下k行每行对应于一条高速公路,由两个数字(xi,yi)组成,xi对应于东城编号,yi西城编号

输出:十字路口数目

分析:

1.对该数组先按y从大到小排序,若y相等,则按x从大到小排序
2.从前往后扫描各条高速公路,对路(xi,yi)其与前面点的交点数目为其左上角路的个数,即所有的(xj,yj),其中xj<xi,yj>yi.
3.与poj 2352类似地,用数组数组c[i]存储x轴的信息

 
  
#include < stdio.h >
#include
< string .h >
#include
< algorithm >
using namespace std;
const int N = 1001 ;
const int K = 1000010 ;

__int64 c[N];
int n,m,k;

struct node
{
int x,y;
bool operator < ( const node & A){ // 先按y从大到小排序,若y相同,按x从小到大排序
if (y == A.y) return x > A.x;
return y >= A.y;
}
}point[K];
inline
int lowbit( int x)
{
return x & ( - x);
}

void modify( int x, int add)
{
while (x <= n)
{
c[x]
+= add;
x
+= lowbit(x);
}
}
__int64 sum(
int x)
{
__int64 ans
= 0 ;
while (x > 0 )
{
ans
+= c[x];
x
-= lowbit(x);
}
return ans;
}
int main()
{
int T;
while (scanf( " %d " , & T) != EOF)
{
int cases;
for (cases = 1 ;cases <= T;cases ++ )
{
memset(c,
0 , sizeof (c));

scanf(
" %d%d%d " , & n, & m, & k);
int i;
__int64 pnum
= 0 ; // 点个数
for (i = 0 ;i < k;i ++ )
{
int xx,yy;
scanf(
" %d%d " , & xx, & yy);

{

point[pnum].x
= xx;
point[pnum].y
= yy;
pnum
++ ;
}
}

sort(point,point
+ pnum); // 对其排序

__int64 ans
= 0 ;
for (i = 0 ;i < pnum;i ++ )
{
modify(point[i].x,
1 );
ans
+= sum(point[i].x - 1 );
}
printf(
" Test case %d: %I64d\n " ,cases,ans);
}
}
return 0 ;
}

转载于:https://www.cnblogs.com/AndreMouche/archive/2011/02/10/1950916.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值