hihocoder1524
描述
给定一个1-N的排列A1, A2, ... AN,如果Ai和Aj满足i < j且Ai > Aj,我们就称(Ai, Aj)是一个逆序对。
求A1, A2 ... AN中所有逆序对的数目。
输入
第一行包含一个整数N。
第二行包含N个两两不同整数A1, A2, ... AN。(1 <= Ai <= N)
对于60%的数据 1 <= N <= 1000
对于100%的数据 1 <= N <= 100000
输出
一个整数代表答案
- 样例输入
-
5
3 2 4 5 1 - 样例输出
-
5
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
#include<iomanip>
using namespace std; //1524 : 逆序对
const int maxn = 1e5 + ;
int n;
long long a[maxn], b[maxn];
int lowbit(int i)
{
return i&-i;
}
void update(int i)
{
while (i <= n)
{
b[i]++;
i += lowbit(i);
}
}
long long sum(int i)
{
long long cnt = ;
while (i)
{
cnt += b[i];
i -= lowbit(i);
}
return cnt;
}
int main()
{
cin >> n;
for (int i = ;i <= n;i++)
{
cin >> a[i];
}
memset(b, , sizeof(b));
long long res = ;
for (int i = n;i >= ;i--)
{
update(a[i]);
res += sum(a[i] - );
}
cout << res << endl;
return ;
}
树形数组这个东西还是比较有趣的。这个算法可以说是比较天才了。
具体的树形数组详解可以看这个博主的http://blog.csdn.net/ljd4305/article/details/10101535
归并排序的ac代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
#include<iomanip>
using namespace std; //1524 : 逆序对
const int maxn = 1e5 + ;
int n;
long long a[maxn],b[maxn];
long long cnt; void merge_sort(long long * a, int l, int r)
{
int mid = (l + r) >> ;
int m = l, n = mid + ;
int pos = l;
while (m<=mid&&n<=r)
{
if (a[m] < a[n])
{
b[pos++] = a[m++];
}
else
{
b[pos++] = a[n++];
cnt+=mid-m+;
}
} while (m <= mid) b[pos++] = a[m++];
while (n <= r) b[pos++] = a[n++];
for (int i = l;i <= r;i++)
a[i] = b[i];
}
void merge(long long * a, int l, int r)
{
if (l >= r) return;
int mid = (l + r) >>;
merge(a, l, mid);
merge(a, mid+, r);
merge_sort(a, l, r);
} int main()
{
cnt = ;
cin >> n;
for (int i = ;i <= n;i++)
{
cin >> a[i];
}
merge(a, , n);
cout << cnt << endl;
return ;
}
归并排序是将数列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。因此,可以在归并排序中的合并过程中计算逆序数。
可以参考http://blog.csdn.net/acdreamers/article/details/16849761
hihocoder1524的更多相关文章
- 树形数组 java
2^k求法 int lowbit(int x) { return x&(-x); } lowbit()的返回值就是 2^k 次方的值. 基本树形数组的模板 import java.util.* ...
随机推荐
- [转] Immutable 常用API简介
本文主要整理了Immutable.js常用API的使用. Immutable 是什么? 关于Immutable的定义,官方文档是这样说的: Immutable data encourages pure ...
- bzoj4773: 负环
题解: 网上还有一种spfa+深度限制的算法 https://www.cnblogs.com/BearChild/p/6624302.html 是不加队列优化的spfa,我觉得复杂度上限是bellma ...
- 强大的xargs
xargs 命令是最重要的 Linux 命令行技巧之一.你可以使用这个命令将命令的输出作为参数传递给另一个命令.例如,搜索 png 文件然后对其进行压缩或者其它操作: find. -name *.pn ...
- python_异常处理_断言
一.Python标准异常 常用异常 Exception 常规错误的基类 AttributeError 试图访问一个对象没有的属性 IOError 输入/ 输出异常,基本上是无法打开文件 ImportE ...
- Flask--第三个例子,写一个接口,该接口返回html前端页面,模板的使用
将接口数据返回至html前端页面有两种方法 方法一: 1 @app.route('/index',methods=['get']) 2 def open_index(): 3 page=open(' ...
- Spring(二)IOC底层实现原理
IOC原理 将对象创建交给Spring去管理. 实现IOC的两种方式 IOC配置文件的方式 IOC注解的方式 IOC底层实现原理 底层实现使用的技术 1.1 xml配置文件 1.2 dom4j解析xm ...
- hdu 2091空心三角形
把一个字符三角形掏空,就能节省材料成本,减轻重量,但关键是为了追求另一种视觉效果.在设计的过程中,需要给出各种花纹的材料和大小尺寸的三角形样板,通过电脑临时做出来,以便看看效果. Input每行包含 ...
- HDFS格式化namenode后启动集群datanode不启动
这是因为格式化namenode之后,namenode节点中VERSION的ClusterID会改变!!! 解决办法: 1.打开namenode节点的hdfs-site.xml文件,查看你的nameno ...
- Java中的不同遍历方式
已知一个Person类: public class Person implements Comparable<Person>{ String name; String id; public ...
- Linux学习之源码包安装与脚本安装(十八)
Linux学习之源码包安装与脚本安装 目录 源码包与RPM包的区别 源码包安装 脚本安装 源码包与RPM包的区别 1.区别 安装之前的区别:概念上的区别 安装之后的区别:安装位置不同 源码包: 开源的 ...