题目描述

猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计。最近,TOM老猫查阅到一个人类称之为“逆序对”的东西,这东西是这样定义的:对于给定的一段正整数序列,逆序对就是序列中ai>aj且i<j的有序对。知道这概念后,他们就比赛谁先算出给定的一段正整数序列中逆序对的数目。

输入输出格式

输入格式:

第一行,一个数n,表示序列中有n个数。

第二行n个数,表示给定的序列。

输出格式:

给定序列中逆序对的数目。

输入输出样例

输入样例#1:

6
5 4 2 6 3 1
输出样例#1:

11

说明

对于50%的数据,n≤2500

对于100%的数据,n≤40000。

代码:解法一

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int N,a[],temp[],cnt; void print(){
for(int i=;i<=;i++){
printf("%d ",a[i]);
}
puts("");
} void merge_sort(int l,int r){
if(l>=r) return;
int mid=(l+r)>>;
merge_sort(l,mid);merge_sort(mid+,r); int i=l,j=mid+,point=l;
while(i<=mid&&j<=r){
if(a[i]>a[j]){
temp[point++]=a[j++];
cnt+=(mid-i+);
}
else{
temp[point++]=a[i++];
}
} while(i<=mid) temp[point++]=a[i++];
while(j<=r) temp[point++]=a[j++]; for(int k=l;k<=r;++k)
a[k]=temp[k];
// print();
} int main(){
// freopen("01.txt","r",stdin); scanf("%d",&N);
for(int i=;i<=N;++i)
scanf("%d",&a[i]); merge_sort(,N); printf("%d\n",cnt);
return ;
}

暴力枚举的话,可以过两个点~

转载题解如下:http://blog.csdn.net/acdreamers/article/details/16849761

归并排序是将数列a[l,h]分成两半a[l,mid]和a[mid+1,h]分别进行归并排序,然后再将这两半合并起来。

在合并的过程中(设l<=i<=mid,mid+1<=j<=h),当a[i]<=a[j]时,并不产生逆序数;当a[i]>a[j]时,在

前半部分中比a[i]大的数都比a[j]大,将a[j]放在a[i]前面的话,逆序数要加上mid+1-i。因此,可以在归并

排序中的合并过程中计算逆序数.

解法二:树状数组+离散化

 #include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std; const int N = ; struct Node
{
int val;
int pos;
}; Node node[N];
int c[N], reflect[N], n; bool cmp(const Node& a, const Node& b)
{
return a.val < b.val;
} int lowbit(int x)
{
return x & (-x);
} void update(int x)
{
while (x <= n)
{
c[x] += ;
x += lowbit(x);
}
} int getsum(int x)
{
int sum = ;
while (x > )
{
sum += c[x];
x -= lowbit(x);
}
return sum;
} int main()
{
while (scanf("%d", &n) != EOF && n)
{
for (int i = ; i <= n; ++i)
{
scanf("%d", &node[i].val);
node[i].pos = i;
}
sort(node + , node + n + , cmp); //排序
for (int i = ; i <= n; ++i) reflect[node[i].pos] = i; //离散化
for (int i = ; i <= n; ++i) c[i] = ; //初始化树状数组
long long ans = ;
for (int i = ; i <= n; ++i)
{
update(reflect[i]);
ans += i - getsum(reflect[i]);
}
printf("%lld\n", ans);
}
return ;
}

转载自http://blog.csdn.net/alongela/article/details/8142965

给定n个数,要求这些数构成的逆序对的个数。除了用归并排序来求逆序对个数,还可以使用树状数组来求解。

树状数组求解的思路:开一个能大小为这些数的最大值的树状数组,并全部置0。从头到尾读入这些数,每读入一个数就更新树状数组,查看它前面比它小的已出现过的有多少个数sum,然后用当前位置减去该sum,就可以得到当前数导致的逆序对数了。把所有的加起来就是总的逆序对数。

题目中的数都是独一无二的,这些数最大值不超过999999999,但n最大只是500000。如果采用上面的思想,必然会导致空间的巨大浪费,而且由于内存的限制,我们也不可能开辟这么大的数组。因此可以采用一种称为“离散化”的方式,把原始的数映射为1-n一共n个数,这样就只需要500000个int类型的空间。

离散化的方式:

struct Node

{

int val;

int pos;

};

Node node[500005];

int reflect[500005];

val存放原数组的元素,pos存放原始位置,即node[i].pos = i。

把这些结构体按照val的大小排序。

reflect数组存放离散化后的值,即reflect[node[i].pos] = i。

这样从头到尾读入reflect数组中的元素,即可以保持原来的大小关系,又可以节省大部分空间。

这个可以辅助理解

http://blog.csdn.net/cattycat/article/details/5640838

树状数组实际上还是一个数组,只不过它的每个元素保存了跟原来数组的一些元素相关的结合值。

若A为原数组,定义数组C为树状数组。C数组中元素C[ i ]表示A[ i –lowbit( i ) + 1]至A[ i ]的结合值。

lowbit(i)是i的二进制中最后一个不为零的位数的2次方,可以这样计算

lowbit(i)=x&(-x)

lowbit(i)=x&(x^(x-1))

洛谷 P1908 逆序对 Label:归并排序||树状数组 不懂的更多相关文章

  1. 洛谷P1908 逆序对(线段树解法)

    题目描述 猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计.最近,TOM老猫查阅到一个人类称之为“逆序对”的东西,这东西是这样定 ...

  2. [NOIP2013提高&洛谷P1966]火柴排队 题解(树状数组求逆序对)

    [NOIP2013提高&洛谷P1966]火柴排队 Description 涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度. 现在将每盒中的火柴各自排成一列, 同一列火柴的高度互不相 ...

  3. BZOJ_3295_[Cqoi2011]动态逆序对_CDQ分治+树状数组

    BZOJ_3295_[Cqoi2011]动态逆序对_CDQ分治+树状数组 Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一 ...

  4. 洛谷 P1908 逆序对(归并排序解法)

    树状数组解法:https://www.cnblogs.com/lipeiyi520/p/10846927.html 题目描述 猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不 ...

  5. 洛谷 P1908 逆序对(树状数组解法)

    归并排序解法:https://www.cnblogs.com/lipeiyi520/p/10356882.html 题目描述 猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不 ...

  6. 洛谷P1908 逆序对 [权值线段树]

    题目传送门 逆序对 题目描述 猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计.最近,TOM老猫查阅到一个人类称之为“逆序对”的 ...

  7. 洛谷P1908 逆序对 (树状数组+离散化)

    模板题,树状数组加上离散化求逆序对. 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 ...

  8. 洛谷P1908 逆序对

    P1908 逆序对 2.2K通过 4.4K提交 题目提供者该用户不存在 标签云端 难度普及/提高- 时空限制1s / 128MB 提交  讨论  题解 最新讨论更多讨论 归并排序党注意了!数组要开… ...

  9. 洛谷 P1908 逆序对

    \[传送门qwq\] 题目描述 猫猫\(TOM\)和小老鼠\(JERRY\)最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计. 最近,\(TOM\)老猫查阅 ...

随机推荐

  1. hrb 2134 素数

    分拆素数和 Time Limit: 1000 MS Memory Limit: 32768 K Total Submit: 176(99 users) Total Accepted: 106(93 u ...

  2. C++中new的解说

    new int;//开辟一个存放整数的存储空间,返回一个指向该存储空间的地址(即指针) new int(100);//开辟一个存放整数的空间,并指定该整数的初值为100,返回一个指向该存储空间的地址 ...

  3. Linux LVS Nginx HAProxy 优缺点

    说明:以下内容参考了抚琴煮酒的<构建高可用Linux服务器>第六章内容. 搭建负载均衡高可用环境相对简单,主要是要理解其中原理.此文描述了三种负载均衡器的优缺点,以便在实际的生产应用中,按 ...

  4. django-cms 代码研究(三)插件(plugs in)

    插件(plugs in) djangocms支持的插件有: http://docs.django-cms.org/en/latest/basic_reference/plugin_reference. ...

  5. 使用git如何批量对文件进行rm操作

    git add -A 它会把我们未通过 git rm 删除的文件全部stage 转自: http://segmentfault.com/q/1010000000095373

  6. tesseract3.02识别验证码需要注意的问题

    1.安装tesseract3.02后,在命令行里输入tesseract,看能否出现使用方法,不出现则是环境变量问题,可调整其顺序. 2.找到如下文件 C:\Python27\Lib\site-pack ...

  7. 关于Xcode6 Segue 的疑问,没有解决!

    xcode6 的segue 变化了,如图 关于前3个选项,始终没有太明白,我试验结果如下,简单地把几个viewController连接起来时,无论用show,还是showdetail,还是Presen ...

  8. 双系统重装windows后修复UBUNTU的GRUB

    1.问题背景 本子是win7和ubuntu10.04双系统,用的还算好,虽然只有在用QQ的时候还会用到win7,但还是保留windows.可是几天 前,win7突然总是蓝屏.死机,更重要是的背景变成黑 ...

  9. c++ template函数的声明和实现需要在同一个文件中

    新建一个class C;生成2个文件C.h和C.cpp,在C.h中声明一个函数 template<class T> T stringTo(char* str); 直接用VAssistX的R ...

  10. linux 小喇叭 没了

    Waiting for sound system to respond 方法: # pulseaudio --start -D W: main.c: This program is not inten ...