• Codeforces Round #790 (Div. 4) H. Maximum Crossings


    H1. Maximum Crossings (Easy Version)

    H2. Maximum Crossings (Hard Version)

    Let’s look at two wires from i i i a i a_i ai and j j j a j a_j aj.

    • If a i a_i ai < a j a_j aj, there can never be any intersection.
    • If a i a_i ai > a j a_j aj, there has to be an intersection.
    • If a i a_i ai = a j a_j aj, it is possible that there is an intersection or not, depending on how we arrange the wires on the bottom terminal.

    In the last case, if there are multiple wires that go to the same segment a i a_i ai, we can make all pairs of them cross by arranging the points in which they hit this segment from right to left. For example, if a = [ 1 , 1 , 1 , 1 ] a=[1,1,1,1] a=[1,1,1,1], then we can make all pairs of segments cross as shown.

    在这里插入图片描述
    Since we want to maximize the number of intersections, we just need to count the number of pairs ( i , j ) (i,j) (i,j) such that a i a_i ai ≥ ≥ a j a_j aj. You can brute force all pairs in O ( n 2 ) O(n^2) O(n2).

    #include
    using namespace std;
    
    int main()
    {
        int T;cin>>T;
        while(T--)
        {
            int n;cin>>n;
            vector<int> a(n);
            for(int i=0;i<n;i++) cin>>a[i];
            int res=0;
            for(int i=0;i<n;i++)
                for(int j=i+1;j<n;j++)
                    if(a[i]>=a[j])
                        res++;
            cout<<res<<endl;
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    Read the solution of the easy version.
    We want to count the number of pairs ( i , j ) (i,j) (i,j) such that i < j ii<j and a i a_i ai ≥ ≥ a j a_j aj. This is a standard problem, and we can do this we can use a segment tree or BIT, for example. Insert the a j a_j aj from j j j = = = 1 1 1 to n, and then for each a j a_j aj count the number of a i a_i ai ≤ ≤ a j a_j aj using a BIT.

    It is also related to the problem of counting inversions, so you can solve it using a modification of merge sort.

    Either way, the solution is O ( n l o g n ) O(nlogn) O(nlogn).

    #include
    using namespace std;
    
    typedef long long LL;
    const int N = 200010;
    
    int tr[N],a[N],n;
    
    void add(int x,int y)
    {
        for(;x<=n;x+=(x&-x))
            tr[x]+=y;
    }
    
    LL query(int x)
    {
        LL res=0;
        for(;x;x-=(x&-x))
            res+=tr[x];
        return res;
    }
    
    int main()
    {
        int T;cin>>T;
        while(T--)
        {
            memset(tr,0,sizeof tr);
            cin>>n;
            for(int i=0;i<n;i++) cin>>a[i];
            LL res=0;
            for(int i=0;i<n;i++)
            {
                res+=query(n)-query(a[i]-1);
                add(a[i],1);
            }
            cout<<res<<endl;
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
  • 相关阅读:
    List 常见实现类源码解析:ArrayList、LinkedList、Vector
    06 【Sass语法介绍-函数】
    HW学习笔记
    电商仓储物流是什么?
    IOS硬件模拟定位原理
    《VS2013+ Qt5.6 创建Qt对话框(*.ui 文件, *.h, *.cpp )》
    3Dmax中VR渲染太阳光渲染参数怎么设置?渲染100云渲染助力
    Matlab:有关字符串数组的常见问题解答
    类加载器源码分析-双亲委派机制
    Go语言读取文件内容
  • 原文地址:https://blog.csdn.net/qq_52792570/article/details/127782445