码迷,mamicode.com
首页 > 编程语言 > 详细

POJ3067 Japan【树状数组】【逆序数】

时间:2015-05-13 23:17:10      阅读:165      评论:0      收藏:0      [点我收藏+]

标签:

题目链接:

http://poj.org/problem?id=3067


题目大意:

有两排的城市,一排N个城市,编号为1~N,一排M个城市,编号为1~M。这两排城市之间有K条路。

路都是直线连接,问:这些路,有多少道路是相交的,并且焦点不是城市所在的点,求出交点个数。


思路:

树状数组的思想。参考网上的图,先将所有边(u,v)按u升序排列,如果u相同,则按v升序排列。可

以看出来,路(u1,v1)和路(u2,v2)如果有交点的话,u1 > u2 并且 v1 < v2,或者 u1 < u2 并且

v1 > v2,为了不重复计算,忽略后一种情况。如果排序完之后,可以发现:结果就是右边序列的逆

序数。直接建立树状数组求逆序数即可。

技术分享

例如题中例子,如上图所示。排完序为:

1 4

2 3

3 1

3 2

交点个数为:0+1+2+2 = 5个。


AC代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define LL __int64
using namespace std;
const int MAXN = 1000;

int Tree[MAXN+10];

struct Node
{
    int u,v;
}Edges[MAXN*MAXN];

int cmp(Node a,Node b)
{
    if(a.u != b.u)
        return a.u < b.u;
    else
        return a.v < b.v;
}

int Lowbit(int x)
{
    return x & (-x);
}

void Update(int i,int x)
{
    while(i <= MAXN)
    {
        Tree[i] += x;
        i += Lowbit(i);
    }
}

LL Query(int n)
{
    LL sum = 0;
    while(n > 0)
    {
        sum += Tree[n];
        n -= Lowbit(n);
    }
    return sum;
}

int main()
{
    int T,N,M,K,kase = 0;
    scanf("%d",&T);
    while(T--)
    {
        memset(Tree,0,sizeof(Tree));
        scanf("%d%d%d",&N,&M,&K);
        for(int i = 0; i < K; ++i)
            scanf("%d%d",&Edges[i].u,&Edges[i].v);
        sort(Edges,Edges+K,cmp);
        LL ans = 0;
        for(int i = 0; i < K; ++i)
        {
            ans += i-Query(Edges[i].v);
            Update(Edges[i].v,1);
        }
        printf("Test case %d: %I64d\n",++kase, ans);
    }

    return 0;
}


POJ3067 Japan【树状数组】【逆序数】

标签:

原文地址:http://blog.csdn.net/lianai911/article/details/45700765

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!