• Poj2299---Ultra-QuickSort


    Ultra-QuickSort

    题目链接:http://poj.org/problem?id=2299

    思路:求逆序数。

    问题1?0 ≤ a[i] ≤ 999,999,999设置的用意?

    1)采用O(n2)的模拟方法过不了

    查找每一个值的逆序数,每个数查找一轮,n个数查找n轮,时间复杂度O(n2)。

    2)改用其他方法:线段树(ok),树状数组(ok)

    这里我们使用的是树状数组:

    假设原数组:9 1 0 5 4 

    假设直接使用树状数组,其对应的树状数组为:

    下标 0 1 2 3 4 5 6 7 8 9

    数组 1 1 0 0 1 1 0 0 0 1(基于一系列的updata操作以后)

    结论:浪费空间

    采用树状数组前我们先对其进行离散化:

    9 1 0 5 4 ------- 离散后的数组就是 5 2 1 4 3;

    3)流程:

    9 1 0 5 4 ------- 离散后的数组就是 5 2 1 4 3;

    树状数组一开始全为0

    原:5 2 1 4 3

    树:0 0 0 0 0 

     

    1---->输入5,   调用upDate(5, 1),把第5位设置为1

    1 2 3 4 5

    0 0 0 0 1

    计算1-5上比5小的数字存在么? 这里用到了树状数组的getSum(5) = 1操作,

    现在用输入的下标1 - getSum(5) = 0 就可以得到对于5的逆序数为0。

    2---->输入2, 调用upDate(2, 1),把第2位设置为1

    1 2 3 4 5

    0 1 0 0 1

    计算1-2上比2小的数字存在么? 这里用到了树状数组的getSum(2) = 1操作,

    现在用输入的下标2 - getSum(2) = 1 就可以得到对于2的逆序数为1。

    3---->输入1, 调用upDate(1, 1),把第1位设置为1

    1 2 3 4 5

    1 1 0 0 1

    计算1-1上比1小的数字存在么? 这里用到了树状数组的getSum(1) = 1操作,

    现在用输入的下标 3 - getSum(1) = 2 就可以得到对于1的逆序数为2。

    4----> 输入4, 调用upDate(4, 1),把第5位设置为1

    1 2 3 4 5

    1 1 0 1 1

    计算1-4上比4小的数字存在么? 这里用到了树状数组的getSum(4) = 3操作,

    现在用输入的下标4 - getSum(4) = 1 就可以得到对于4的逆序数为1。

    5----> 输入3, 调用upDate(3, 1),把第3位设置为1

    1 2 3 4 5

    1 1 1 1 1

    计算1-3上比3小的数字存在么? 这里用到了树状数组的getSum(3) = 3操作,

    现在用输入的下标5 - getSum(3) = 2 就可以得到对于3的逆序数为2。

    6----> 0+1+2+1+2 = 6 这就是最后的逆序数

     

     

    代码:

    #include<iostream>
    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn=500005;
    int n;
    int aa[maxn]; //离散化后的数组
    int c[maxn];    //树状数组
     
    struct Node{
       int v;
       int order;
    }in[maxn];
     
    int lowbit(int x){
        return x&(-x);
    }
     
    void update(int t,int value){
        int i;
        for(i=t;i<=n;i+=lowbit(i))
        {
            c[i]+=value;
        }
    }
     
    int getsum(int x){
        int i;
        int temp=0;
        for(i=x;i>=1;i-=lowbit(i)){
            temp+=c[i];
        }
        return temp;
    }
     
    bool cmp(Node a ,Node b){
        return a.v<b.v;
    }
     
    int main(){
        while(scanf("%d",&n)==1 && n){
            //离散化
            for(int i=1;i<=n;i++){
                scanf("%d",&in[i].v);
                in[i].order=i;
            }
            sort(in+1,in+n+1,cmp);
            for (int i = 1; i <= n; i++)
            {
                cout<<in[i].v<<" ";
            }
            cout<<endl;
            for (int i = 1; i <= n; i++)
            {
                cout<<in[i].order<<" ";
            }
            cout<<endl;
    
            for(int i=1;i<=n;i++) aa[in[i].order]=i;
            for(int i=1;i<=n;i++) cout<<aa[i]<<" ";
            cout<<endl;
            //树状数组求逆序
            memset(c,0,sizeof(c));
            long long ans=0;
            for(int i=1;i<=n;i++){
                update(aa[i],1);
                ans+=i-getsum(aa[i]);
            }
            cout<<ans<<endl;
        }
        return 0;
    }

     

    因上求缘,果上努力~~~~ 作者:每天卷学习,转载请注明原文链接:https://www.cnblogs.com/BlairGrowing/p/14099590.html

  • 相关阅读:
    SetupFactory7使用经验
    中值滤波C语言优化
    回归直线方程
    图像倾斜矫正方程基本的图像变换
    关于相机的一些概念
    VS如何自动创建函数头 函数说明
    自动打开虚拟机
    一些笔记jexcel
    linux 重启mysql redis等服务器
    handsontable 随记
  • 原文地址:https://www.cnblogs.com/BlairGrowing/p/14099590.html
Copyright © 2020-2023  润新知