zoukankan      html  css  js  c++  java
  • CF #301 E:Infinite Inversions(逆序数,树状数组)

    A-Combination Lock  B-School Marks   C-Ice Cave   D-Bad Luck Island   E-Infinite Inversions

    E:Infinite Inversions

    题意就是有一个序列1,2,3,4。。。。。

    现在有n次交换,每次都把ab交换求最终形成的序列的逆序数;

    逆序数分为两部分。一部分是交换过位置的,另一部分是没有交换过的。

    离散化后,利用树状数组求出交换过的位置的逆序数的个数。

    第二部分:

    看一个样例:

    2

    1 6

    9 5

    得到的序列为6 2 3 4 9 1 7 8 5

    首先对于数值6,其下标为1。在区间[1, 6]中,共有6个数。减去该区间中有3个是交换过位置的,则6-3 = 3是数值6对于当前序列所构成的逆序数个数。

    对于数值9,下标为5,则在区间[5,9],共有5个数。减去该区间有3个是换过位置的,则逆序数为2。

    对于数值1,其下标为6,在区间[1,6]中,~~~~~也有3个逆序数。

    ……

    问题变为求一个区间的中有几个是交换过位置的,其实只要知道其下标的排名。例如下标1的排名为1,下标5排名2,下标6排名3,下标9排名4。

    区间[1,6],则是3-1+1 = 3;

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<map>
    #include<cmath>
    #include<queue>
    using namespace std;
    #define N 2010005
    #define INF 0x3f3f3f3f
    
    struct node
    {
        int x, y;
    }b[N];
    map<int, int>M;
    int a[N], cnt, Tree[N], V[N];
    
    int lowbit(int x)
    {
        return x&(-x);
    }
    
    void Update(int pos, int num)
    {
        while(pos<=cnt)
        {
            Tree[pos]+=num;
            pos+=lowbit(pos);
        }
    }
    
    int GetSum(int pos)
    {
        int s=0;
        while(pos)
        {
            s+=Tree[pos];
            pos-=lowbit(pos);
        }
        return s;
    }
    
    int main()
    {
        int n;
        while(scanf("%d", &n)!=EOF)
        {
            memset(a, 0, sizeof(a));
            memset(b, 0, sizeof(b));
            memset(V, 0, sizeof(V));
            cnt=1;
            for(int i=0; i<n; i++)
            {
                scanf("%d %d", &b[i].x, &b[i].y);
                a[cnt++]=b[i].x, a[cnt++]=b[i].y;
            }
            sort(a+1, a+cnt);
            cnt = unique(a, a+cnt)-a-1;
            for(int i=1; i<=cnt; i++)
                M[a[i]]=i, V[i]=i;
            for(int i=0; i<n; i++)
            {
                int p=M[b[i].x];
                int q=M[b[i].y];
                swap(V[p], V[q]);
            }
            long long ans=0;
            memset(Tree, 0, sizeof(Tree));
            for(int i=1; i<=cnt; i++)
            {
                int x=V[i];
                ans+=(i-1-GetSum(x));
                Update(x, 1);
            }
            for(int i=1; i<=cnt; i++)
                ans+=abs(a[V[i]]-a[i]-V[i]+i);
            printf("%lld
    ", ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    windows8开发学习笔记
    文字超出隐藏并显示省略号
    list-style-type -- 定义列表样式
    抄录:系统集成项目管理42个子过程
    系统集成项目管理工程师--总结(4章)
    系统集成管理项目工程师总结--口诀2(包含1)
    系统集成管理项目工程师总结--法律法规日期篇1
    关于EAI(一个同学问了我很可爱的问题所以查到的这些)要看看
    系统集成项目管理工程师计划
    中级
  • 原文地址:https://www.cnblogs.com/zhengguiping--9876/p/4977818.html
Copyright © 2011-2022 走看看