zoukankan      html  css  js  c++  java
  • poj 2299 UltraQuickSort

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

    一开始敲了一个冒泡,但是一看数据范围很大,会超时,然后想了想也没想出来什么好的方法,搜了一下解题报告,是逆序数的问题,线代学的不好,都忘了,搜了一下,用的是归并,还有一个方法是树状数组,没接触过树状数组,所以有了解了一下树状数组

    归并:

    在合并的过程中是将两个相邻并且有序的序列合并成一个有序序列,如以下两个有序序列

    Seq13  4  5

    Seq22  6  8  9

    合并成一个有序序:

    Seq2  3  4  5  6  8  9

    对于序列seq1中的某个数a[i],序列seq2中的某个数a[j],如果a[i]<a[j],没有逆序数,如果a[i]>a[j],那么逆序数为seq1a[i]后边元素的个数(包括a[i]),即len1-i+1,

    这样累加每次递归过程的逆序数,在完成整个递归过程之后,最后的累加和就是逆序的总数

    注:要用__int64,long和long long会wa

    代码:

    View Code
     1 #include <iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 __int64 a[500010];
     5 __int64 b[500010];
     6 __int64 merge(int low,int mid,int high)
     7 {
     8     int i=low,j=mid+1;
     9     int k=0;
    10     __int64 num=0;
    11     while(i<=mid&&j<=high)
    12     {
    13         if(a[i]<=a[j])
    14         b[k++]=a[i++];
    15         else
    16         {
    17             b[k++]=a[j++];
    18             num+=mid-i+1;
    19         }
    20     }
    21     while(i<=mid)
    22     {
    23         b[k++]=a[i++];
    24     }
    25     while(j<=high)
    26     {
    27         b[k++]=a[j++];
    28     }
    29     k=0;
    30     for(i=low;i<=high;i++)
    31     {
    32         a[i]=b[k];
    33         k++;
    34     }
    35     return num;
    36 }
    37 __int64 mergesort(int a,int b)
    38 {
    39     if(a<b)
    40     {
    41         int mid;
    42         __int64 count=0;
    43         mid=(a+b)/2;
    44         count+=mergesort(a,mid);
    45         count+=mergesort(mid+1,b);
    46         count+=merge(a,mid,b);
    47         return count;
    48     }
    49     return 0;
    50 }
    51 
    52 int main()
    53 {
    54     int n,i;
    55     while(scanf("%d",&n)!=EOF)
    56     {
    57         if(n==0)
    58         break;
    59         for(i=0;i<n;i++)
    60         {
    61             scanf("%I64d",&a[i]);
    62         }
    63 
    64         printf("%I64d\n",mergesort(0,n-1));
    65     }
    66     return 0;
    67 }

    树状数组:

    序列:

    3  5  4  8  2  6  9

    先将原序列从大到小排序;

    初始化一个数组

    0  0  0  0  0  0  0

    将最大的元素的位置变为1

    0  0  0  0  0  0  1

    然后放第二大的元素

    0  0  0  1  0  0  1

    。。。。。

    依次进行下去,每次统计在该位置之前的放的元素的个数,然后相加,就是逆序数的总数。

    统计每个位置之前的元素的个数的时候可以用树状数组实现

    代码:

    View Code
     1 #include <iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 using namespace std;
     6 struct node
     7 {
     8     __int64 data;
     9     __int64 pos;
    10 }su[500010];
    11 int tree[500010];
    12 __int64 num;
    13 __int64 n;
    14 
    15 __int64 lowbit(__int64 num)
    16 {
    17     return num&(num^(num-1));
    18 }
    19 
    20 __int64 sum(__int64 pos)
    21 {
    22     __int64 ans=0;
    23     while(pos>0)
    24     {
    25         ans+=tree[pos];
    26         pos-=lowbit(pos);
    27     }
    28     return ans;
    29 }
    30 void update(__int64 pos)
    31 {
    32     while(pos<=n)
    33     {
    34         tree[pos]++;
    35         pos+=lowbit(pos);
    36     }
    37 }
    38 bool cmp(node a,node b)
    39 {
    40     return a.data>b.data;
    41 }
    42 int main()
    43 {
    44 
    45     while(scanf("%I64d",&n)!=EOF)
    46     {
    47         if(n==0)
    48         break;
    49         int i;
    50         for(i=1;i<=n;i++)
    51         {
    52             scanf("%I64d",&su[i].data);
    53             su[i].pos=i;
    54         }
    55         sort(su+1,su+n+1,cmp);
    56         num=0;
    57         memset(tree,0,sizeof(tree));
    58         for(i=1;i<=n;i++)
    59         {
    60             num+=sum(su[i].pos);
    61             update(su[i].pos);
    62         }
    63         printf("%I64d\n",num);
    64     }
    65     return 0;
    66 }
  • 相关阅读:
    尚硅谷《全套Java、Android、HTML5前端视频》
    OCM 学习练习题目
    本文转自 MyEclipse 2015反编译插件安装
    关闭VirtualBox虚拟机的时钟同步
    Oracle数据库的状态查询
    ORA-00845 MEMORY_TARGET not supported on this system 的解决
    Ehcache
    Oracle 列转行函数 Listagg()
    oracle数据库定时任务dbms_job的用法详解
    MySQL 处理海量数据时的一些优化查询速度方法
  • 原文地址:https://www.cnblogs.com/wanglin2011/p/2866890.html
Copyright © 2011-2022 走看看