• POJ 3067 Japan


    题目传送门

    一、题目大意

    两对岸,一边\(n\)个点,一边\(m\)个点,现在连\(k\)条线,问有几个交点。

    二、题目解析

    梳理一下这其实是一个问逆序对的问题,为什么是逆序对?

    举例:

    依题意可得上图,算出\(5\)个点,除了作图还有什么方法可以得到答案呢?我们不妨先把\(n\)的元素看成是有序的,例子就是如此(\(1\) \(2\) \(3\) \(3\))对应的是(\(4\) \(3\) \(2\) \(1\))因为有相同的数据存在,相同位的从小到大排序(\(4\) \(3\) \(1\) \(2\)),如果这个结果是(\(1\) \(2\) \(3\) \(4\))的话,是不是就没有交点了,因为没有逆序对存在。

    把逆序对互换直到为零,操作步数就是\(5\),其实每添加一条线,增加的点数就是增加的逆序对数,还无法理解就按上述步骤模拟几组数据,明白要干什么。

    剩下的就是非常经典的求逆序对问题了。

    三、实现代码

    #include <iostream>
    #include <string.h>
    #include <stdio.h>
    #include <vector>
    #include <map>
    #include <queue>
    #include <algorithm>
    #include <math.h>
    #include <cstdio>
    using namespace std;
    #define lowbit(x) (x & -x)
    typedef long long LL;
    const int N = 1010;
    LL t[N];
    
    struct Node {
        int l, r;
        //按起点由大到小排序,如果起点一样的话,那么按终点由大到小排序
        //求逆序对的结构体
        bool operator<(const Node &W) const {
            if (l == W.l)
                return r > W.r;
            else
                return l > W.l;
        }
    } a[N * N]; // k条边,上限是N*N条
    
    void add(int x, int d) {
        while (x <= N) t[x] += d, x += lowbit(x);
    }
    
    LL getsum(int x) {
        LL sum = 0;
        while (x) sum += t[x], x -= lowbit(x);
        return sum;
    }
    
    int main() {
        int T, cas = 1;
        scanf("%d", &T);
    
        while (T--) {
            memset(t, 0, sizeof(t));
            int n, m, k;
            scanf("%d%d%d", &n, &m, &k); //岸的一边是n个,另一边是m个,下面的n,m没有再次用到
            // k条线
            for (int i = 1; i <= k; i++) scanf("%d%d", &a[i].l, &a[i].r);
            //由大到小排序
            sort(a + 1, a + 1 + k);
    
            LL ans = 0;
            //标准的树状数组求逆序对的过程
            for (int i = 1; i <= k; i++) {
                ans += getsum(a[i].r - 1);
                add(a[i].r, 1);
            }
            //输出
            printf("Test case %d: %lld\n", cas++, ans);
        }
        return 0;
    }
    
    
  • 相关阅读:
    gcc 使用中常用的参数及命令
    Android build system & Android.mk 规范
    ndkgdb对java/native code联合调试
    Android NDK开发指南(一) Application.mk文件
    字符编码知识:Unicode、UTF8、ASCII、GB2312等编码 及 转换
    C & C++ 中值得注意的编译,链接,调试,错误及其原因
    JNI 调用规范
    Graphic 矢量图形的区域填充与缠绕规则
    Android NDK开发指南(二)Android.mk文件
    JNI 之二 :java & c/c++ 相互通信及调用
  • 原文地址:https://www.cnblogs.com/littlehb/p/16228533.html
Copyright © 2020-2023  润新知