• Ultra-QuickSort(归并排序)


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

    此题即为归并排序求逆序数。

     1 #include<stdio.h>
     2 #include<string.h>
     3 const int N=500002;
     4 int a[N],temp[N];
     5 long long  ans;
     6 void merge_arr(int first,int mid,int last)//合并区间
     7 {
     8     int k = 0;
     9     int i = first,n = mid;
    10     int j = mid+1,m = last;
    11     while(i <= n && j <= m)
    12     {
    13         if (a[i] <= a[j])
    14             temp[k++] = a[i++];
    15         else
    16         {
    17             temp[k++] = a[j++];
    18             ans += (mid-i+1);//计算逆序数
    19         }
    20     }
    21     while(i <= n)
    22         temp[k++] = a[i++];
    23     while(j <= m)
    24         temp[k++] = a[j++];
    25     for (i = 0; i < k; i ++)
    26         a[first+i] = temp[i];//将有序的temp[]赋给原数组
    27 }
    28 void mergesort(int first,int last)//归并排序
    29 {
    30     if (first < last)
    31     {
    32         int mid = (first+last)/2;
    33         mergesort(first,mid);
    34         mergesort(mid+1,last);
    35         merge_arr(first,mid,last);
    36     }
    37 }
    38 int main()
    39 {
    40     int n;
    41     while(~scanf("%d",&n)&&n)
    42     {
    43         ans = 0;
    44         for (int i = 0; i < n; i ++)
    45         {
    46             scanf("%d",&a[i]);
    47         }
    48         mergesort(0,n-1);
    49         printf("%lld
    ",ans);
    50     }
    51     return 0;
    52 }
    View Code

    同类型的题:

    http://poj.org/problem?id=1804 

    Brainman

    题意:给出n个数,只能相邻的两个数交换,问最少交换多少次才能使这n个数递增排列。

    思路:求出该序列的逆序数即为最少交换的次数。

    法一:直接暴力o(n^2)

     1 #include <stdio.h>
     2 #include <algorithm>
     3 #include <string.h>
     4 using namespace std;
     5 const int N=1005;
     6 
     7 int a[N];
     8 
     9 int main()
    10 {
    11     int t,o = 0;
    12     scanf("%d",&t);
    13     while(t--)
    14     {
    15         o++;
    16         int n;
    17         scanf("%d",&n);
    18         for (int i = 0; i < n; i++)
    19             scanf("%d",&a[i]);
    20 
    21         int cnt = 0;
    22         for (int i = 0; i < n; i++)
    23         {
    24             for (int j = i+1; j < n; j++)
    25             {
    26                 if (a[i] > a[j])
    27                     cnt++;
    28             }
    29 
    30         }
    31         printf("Scenario #%d:
    %d
    
    ",o,cnt);
    32     }
    33     return 0;
    34 }
    View Code

    法二:归并排序 o(nlogn)

     1 #include <stdio.h>
     2 #include <string.h>
     3 const int N=1002;
     4 const int INF = 1<<28;
     5 long long ans = 0;
     6 void Merge(int *a,int s,int mid,int t)
     7 {
     8     int lenl= mid-s+1;
     9     int lenr = t-mid;
    10     int *b = new int[lenl+2];
    11     int *c = new int[lenr+2];
    12     for (int i = 1; i <= lenl; i++)
    13         b[i] = a[s+i-1];
    14     b[lenl+1] = INF;
    15     for (int i = 1; i <= lenr; i++)
    16         c[i] = a[mid+i];
    17     c[lenr+1] = INF;
    18     int i = 1 ,j = 1,k = s;
    19     while(k <= t)
    20     {
    21         if (b[i] <= c[j])
    22             a[k++] = b[i++];
    23         else
    24         {
    25             a[k++] = c[j++];
    26             ans+=lenl-i+1; //计算逆序数
    27         }
    28     }
    29     delete(b);
    30     delete(c);
    31 }
    32 void MergeSort(int *a,int s,int t)
    33 {
    34     int mid = (s+t)>>1;
    35     if(t <= s)
    36         return ;
    37     MergeSort(a,s,mid);
    38     MergeSort(a,mid+1,t);
    39     Merge(a,s,mid,t);
    40 }
    41 int main()
    42 {
    43     int t,o = 0,a[N],b[N];
    44     scanf("%d",&t);
    45     while(t--)
    46     {
    47         o++;
    48         int n;
    49         ans = 0;
    50         scanf("%d",&n);
    51         for (int i = 1; i <= n; i++)
    52             scanf("%d",&a[i]);
    53         MergeSort(a,1,n);
    54         printf("Scenario #%d:
    %lld
    
    ",o,ans);
    55     }
    56     return 0;
    57 }
    View Code

    法三:树状数组 o(nlogn)

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <algorithm>
     4 using namespace std;
     5 const int N=2000005;
     6 int c[N],a[N],n;
     7 struct node
     8 {
     9     int data;
    10     int pos;
    11     friend bool operator < (const node a,const node b)
    12     {
    13         if(a.data==b.data)
    14             return a.pos < b.pos;
    15         else
    16             return a.data < b.data;
    17     }
    18 } g[N];
    19 int lowbit(int x)
    20 {
    21     return x&(-x);
    22 }
    23 void update(int x,int data)
    24 {
    25     while(x <= N)
    26     {
    27         c[x]+=data;
    28         x+=lowbit(x);
    29     }
    30 }
    31 int sum(int x)
    32 {
    33     int ans = 0;
    34     while(x > 0)
    35     {
    36         ans+=c[x];
    37         x-=lowbit(x);
    38     }
    39     return ans;
    40 }
    41 int main()
    42 {
    43     int t,o = 0;
    44     scanf("%d",&t);
    45     while(t--)
    46     {
    47         o++;
    48         scanf("%d",&n);
    49         for (int i = 1; i <= n; i++)
    50         {
    51             scanf("%d",&g[i].data);
    52             g[i].pos = i;
    53         }
    54         sort(g+1,g+1+n);
    55         memset(c,0,sizeof(c));
    56         for (int i = 1; i <= n; i++)//离散化
    57             a[g[i].pos] = i;
    58         long long ans = 0;
    59         for (int i = 1; i <= n; i++)
    60         {
    61             update(a[i],1);
    62             ans+=i-sum(a[i]);
    63         }
    64         printf("Scenario #%d:
    %lld
    
    ",o,ans);
    65     }
    66     return 0;
    67 }
    View Code
  • 相关阅读:
    Java 单链表的倒置
    Android查询:模拟键盘鼠标事件(adb shell 实现)
    安卓 发送短信两种方式
    java tcp socket实例
    Java中读取某个目录下的所有文件和文件夹
    Android剖析和运行机制
    linux下搭建android NDK开发环境
    把log存起来
    判断Android系统net和wap接入点的开发实例
    android 4.0.4系统下实现apk的静默安装和启动
  • 原文地址:https://www.cnblogs.com/lahblogs/p/3268485.html
Copyright © 2020-2023  润新知