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

来源:互联网 发布:淘宝客优惠券推广 编辑:程序博客网 时间:2024/05/16 10:09

题目链接:

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 __int64using 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;}


0 0
原创粉丝点击