• 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
  • 相关阅读:
    “ResGen.exe”已退出,代码为2 问题处理
    在不同域中各个系统拥有自已独立的用户系统时的单点登录问题
    SQL SERVER 表分区
    用《捕鱼达人》去理解C#中的多线程
    浅谈ThreadPool 线程池(引用)
    解决chrome和firefox flash不透明的方法
    浅谈CSRF攻击方式(转)
    SQL语句创建相同结构的表
    如何识别伪静态网页
    在drop user之前,建议获取该用户的依赖情况
  • 原文地址:https://www.cnblogs.com/zhengguiping--9876/p/4977818.html
Copyright © 2020-2023  润新知