nyoj117求逆序数(离散化+树状数组/归并排序)

原创 2013年12月01日 21:26:52

题目链接:nyoj117

树状数组思路:

首先将输入的数组离散化,使各个元素比较接近,而不是离散的。

离散时用一个结构体,val表示原来输入的数,pos表示下标;接着对结构体按val的大小排序,此时,val和结构体的下标就是一个一一对应的关系,而且满足原来的大小关系。然后用数组reflect存储原来所有的大小信息。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 1000005;
int reflect[N],c[N],n;
struct node
{
    int val;
    int pos;
}s[N];
bool cmp(node x,node y)
{
    if(x.val == y.val) return x.pos < y.pos;
    return x.val < y.val;
}
int lowbit(int x)
{
    return x&(-x);
}
void update(int x)
{
    while(x <= n)
    {
        c[x] += 1;
        x += lowbit(x);
    }
}
long long getsum(int x)//统计比x小的数
{
    long long sum = 0;
    while(x > 0)
    {
        sum += c[x];
        x -= lowbit(x);
    }
    return sum;
}
int main()
{
	int T,i;
	scanf("%d",&T);
	while(T--)
	{
	    scanf("%d",&n);
	    for(i = 1; i <= n; i ++)
            scanf("%d",&s[i].val), s[i].pos = i;
        sort(s+1,s+n+1,cmp);
        for(i = 1; i <= n; i ++)
            reflect[s[i].pos] = i;
        memset(c,0,sizeof(c));
        long long ans = 0;
        for(i = 1; i <= n; i ++)
        {
            update(reflect[i]);
            ans += i - getsum(reflect[i]);//i表示已经插入的数的个数
        }
        printf("%lld\n",ans);
	}
	return 0;
}


归并排序:
#include<stdio.h>
int a[1000005],temp[1000005];
long long sum;
void merge(int left,int mid,int right)
{
	int i = left,j = mid + 1;
	int k = left;
	while(i <=mid && j <= right)
	{
		if(a[i] <= a[j])
			temp[k ++] = a[i ++];
		else
		{
			temp[k ++] = a[j ++];
			sum += mid - i + 1;//关键
		}
	}
	while(i <= mid)
        temp[k ++] = a[i ++];

	while(j <= right)
        temp[k ++] = a[j ++];

	for(i = left ; i <= right; i ++)
		a[i] = temp[i];
}
void msort(int left,int right)
{
	if(left < right)
	{
		int mid = (left + right) >> 1;
		msort(left,mid);
		msort(mid + 1,right);
		merge(left,mid,right);
	}
}
int main()
{
	int i,n,T;
	scanf("%d",&T);
	while(T--)
	{
	    scanf("%d",&n);
		for(i = 0;i < n; i ++)
			scanf("%d",&a[i]);
        sum = 0;
		msort(0,n - 1);
		printf("%lld\n",sum);
	}
	return 0;
}


相关文章推荐

NYOJ-117 求逆序数(离散化+树状数组)/(归并)

求逆序数 时间限制:2000 ms  |  内存限制:65535 KB 难度:5 描述 在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序...

求逆序数模板(树状数组+离散化 || 归并排序法)

求逆序数模板(树状数组+离散化 || 归并排序法)

poj2299Ultra-QuickSort【树状数组求逆序数、离散化】、【归并排序模板】

Description In this problem, you have to analyze a particular sorting algorithm. The algorithm proce...

ACM--归并排序&&树状数组--nyoj 117--求逆序数

求逆序数 时间限制:2000 ms  |  内存限制:65535 KB 难度:5 描述 在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一...

nyoj 117 求逆序数 【树状数组】+【离散化】

这道题的解法真的很好!!! 思路:建立一个结构体包含val和id, val就是输入的数,id表示输入的顺序。然后按照val从小到大排序,如果val相等,那么就按照id排序。 如果没有逆序的...

NYOJ 117 求逆序数 (树状数组 + 离散化思路)

求逆序数 时间限制:2000 ms  |  内存限制:65535 KB 难度:5 描述 在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排...

树状数组(归并排序) 之 求逆序数nyoj117

题目信息:点击打开链接 求逆序数 树状数组求逆序数就是不停的向树状数组中插入值,插入的同时更新树状数组,并统计逆序数的个数,在代码中会详细解释;另外大家会发现这种方法很类似于hash标记,即先开一个...

poj-2299-Ultra-QuickSort-归并排序求逆序数--或树状数组

Description In this problem, you have to analyze a particular sorting algorithm. The algorithm proce...

归并排序 树状数组 求逆序数

Description Bob is a game programming specialist. In his new car race game, there are some racers...

【树状数组or归并排序求逆序数】HDU 1394

http://acm.hdu.edu.cn/showproblem.php?pid=1394  先说一下逆序数的概念: 在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数...
  • leolin_
  • leolin_
  • 2011年05月17日 13:22
  • 679
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:nyoj117求逆序数(离散化+树状数组/归并排序)
举报原因:
原因补充:

(最多只允许输入30个字)