POJ 3067 Japan (树状数组 && 控制变量)

Posted shuaihui

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 3067 Japan (树状数组 && 控制变量)相关的知识,希望对你有一定的参考价值。

题意: 西海岸和东海岸有分别有n (1~n)个和m (1~m)个城市, 两个海岸的城市之间有k条公路连通, 公路会相交, 现在给出城市和公路的信息问你由这些公路组成的复杂交通有多少个交点 (如果两个条公路的起点或者终点相同那这两点不算做相交)

分析:先分析题目案例可以知道当y1>y2时,这样是肯定会有交点的。可以根据这个特性很快就可以发现这个就是个求逆序对的问题。但是又是不完全的正确,因为这样分析出来的答案是6,结果错误。现在在来分析是哪里出现的错误,是(3,1)与(3,2)这里的问题,分析题目可知到,如果起点或者终点相同那就不算是香蕉,所以可以得出结论,如果x相等的时候,逆序对不存在,即将y的值对调。同时我们又可以发现前面的这些性质都是在x按升序的情况下成立,所以现在问题的解决就很简单了,按x升序排,相等的话按照y升序排,然后在求得逆序对。

技术分享图片
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#include<set>
#define LL long long
#define lowbit(i) (i&(-i))
using namespace std;
int c[1001], n, k, m;
void add(int i, int val)
{
    while(i<=m){
        c[i] += val;
        i += lowbit(i);
    }
}
LL sum(int i)
{
    LL ans = 0;
    while(i>0){
        ans += c[i];
        i -= lowbit(i);
    }
    return ans;
}
struct no
{
    int x, y;
}arr[10000000];
bool cmp(const no fir, const no sec)
{
    if(fir.x == sec.x) return fir.y < sec.y;
    return fir.x < sec.x;
}
int main(void)
{
    int nCase;
    scanf("%d", &nCase);
    for(int t=1; t<=nCase; t++){
        memset(c, 0, sizeof(c));
        scanf("%d%d%d", &n, &m, &k);
        for(int i=0; i<k; i++){
            scanf("%d%d", &arr[i].x, &arr[i].y);
        }
        sort(arr, arr+k, cmp);
        LL ans = 0;
        for(int i=0; i<k; i++){
            ans += i - sum(arr[i].y);
            add(arr[i].y, 1);
        }
        printf("Test case %d: %lld
", t, ans);
    }
    return 0;
}
View Code

 

以上是关于POJ 3067 Japan (树状数组 && 控制变量)的主要内容,如果未能解决你的问题,请参考以下文章

POJ 3067-Japan-树状数组

POJ3067:Japan(树状数组求逆序对)

poj3067Japan——树状数组查找逆序对

(POJ 3067) Japan (慢慢熟悉的树状数组)

POJ-3067 Japan---树状数组逆序对变形

POJ——T 3067 Japan