poj2299 归并与分治

通过此题理解了所谓的分治, 挺简单的,具体思路就是先二分一样分数组, 后在合并的过程中排序,(本体用到了逆序数)合并的过程就是

将两个数组中的数合并多一个数组中去, 使其有序。(其中设置最大值的岗哨十分重要)具体合并代码如下:
for(int k = l; k <= r; k++)
      if(left1[i] < right1[j]){


        num[k] = left1[i++];


      }else {


        ans += n1 - i + 1;
        num[k] = right1[j++];
      }
#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

const int M  = 500010;

int left1[M];
int  right1[M];
int num[M];
__int64 ans;
int n;

void mergesum(int *num, int l, int mid, int r) {

    int n1 = mid - l + 1;
    int n2 = r - mid;

    for(int i = 1; i <= n1; i++)
        left1[i] = num[l+i -1];
    for(int i = 1; i <= n2; i++)
        right1[i] = num[mid+i];
    left1[n1+1] = 1e9;  //两个岗哨的设置十分重要, 不然会出现溢出现象。
    right1[n2+1] = 1e9;
    int i = 1, j = 1;

    for(int k = l; k <= r; k++)
      if(left1[i] < right1[j]){

        num[k] = left1[i++];

      }else {

        ans += n1 - i + 1;
        num[k] = right1[j++];
      }
}

void mergesort(int *num, int l, int r) {

        if(l < r) {

        int mid = (r + l)/2;
        mergesort(num, l, mid);  //进行分治操作。
        mergesort(num, mid + 1, r);
        mergesum(num, l, mid, r);  //进行合并操作。
    }
}

int main()
{
    while(scanf("%d", &n) != EOF) {

        if(!n)
            break;
       for(int i = 1; i <= n; i++)
        scanf("%d", &num[i]);
        ans = 0;
        mergesort(num, 1, n);
        for(int i = 1; i <= n; i++)
            printf("%d ", num[i]);
        printf("\n");
        printf("%I64d\n", ans);
    }

    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值