一、题目描述

There is a permutation P with n integers from 1 to n. You have to calculate its inversion number, which is the number of pairs of Pi and Pj satisfying the following conditions: iPj.

二、输入

The input may contain several test cases.

In each test case, the first line contains a positive integer n (n<=100000) indicating the number of elements in P. The following n lines contain n integers making the permutation P.

Input is terminated by EOF.

三、输出

For each test case, output a line containing the inversion number.

四、解题思路

题意:求逆序

思路:

1.对整个输入序列,从前往后扫,统计比a[i]小的,在a[i]后面的有多少个,进行累加。这种方法是暴力做法。复制度为n^2。

2)统计a[i]前面的比它大的数

这样利用输入时,已经知道前面的序列,每输入一个数,就把这个数的num[i]值加1,然后统计比这个数大的数的num和,因为这里的和一定是在这个数列中比a[i]大,且在它前面出现的数之和,再把这个和加到总逆序数sum里。

3)在统计比这个数大的数的num和这一步,可以进行优化处理,使用线段树求区间域值,时间复杂度是logn,所以总体复杂度就降到了nlogn。

4)线段树的图如下:

附:这道题也可以使用归并排序的方法。

五、代码

#include<iostream>
#include <cstdio>
#include <cstring>
#include <algorithm> using namespace std; const int MAX_NUM = 110000; struct Node
{
int lChild, rChild;
int num;
}segTree[MAX_NUM*3]; void Build(int lChild, int rChild, int i)
{
segTree[i].lChild = lChild;
segTree[i].rChild = rChild;
segTree[i].num = 0;
if(lChild == rChild)return; int mid = (lChild + rChild) >> 1;
Build(lChild, mid, i << 1);
Build(mid + 1, rChild, i + i + 1);
} void update(int t, int o)
{
if(segTree[o].lChild == segTree[o].rChild && segTree[o].lChild == t)
{
segTree[o].num++;
return;
} int mid = (segTree[o].lChild + segTree[o].rChild) >> 1;
if(t > mid) update(t, o + o +1);
else update(t, o + o);
segTree[o].num = segTree[o+o].num + segTree[o + o + 1].num;
} int query(int lChild, int rChild, int i)
{
if(segTree[i].lChild == lChild && segTree[i].rChild == rChild)
return segTree[i].num;
int mid = (segTree[i].lChild + segTree[i].rChild) >> 1;
if(rChild <= mid) return query(lChild, rChild, i + i);
else if(lChild > mid) return query(lChild, rChild, i + i + 1);
else return query(lChild, mid, i * 2) + query(mid+1, rChild, i * 2 + 1);
} int main()
{
int num;
while(cin >> num)
{
int dataArray[MAX_NUM];
int inputData;
for(int i = 0; i < num; i++)
{
cin >> inputData;
dataArray[i] = inputData;
} Build(1, num, 1); long long result = 0; for(int i = 0; i < num; i++)
{
result += query(dataArray[i], num, 1);
update(dataArray[i], 1);
} cout << result << endl;
} return 0;
}

<Sicily>Inversion Number(线段树求逆序数)的更多相关文章

  1. [HDU] 1394 Minimum Inversion Number [线段树求逆序数]

    Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java ...

  2. HDU_1394_Minimum Inversion Number_线段树求逆序数

    Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java ...

  3. hdu1394--Minimum Inversion Number(线段树求逆序数,纯为练习)

    Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Ot ...

  4. HDU-1394 Minimum Inversion Number(线段树求逆序数)

    Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Ot ...

  5. 线段树求逆序数方法 HDU1394&amp;&amp;POJ2299

    为什么线段树能够求逆序数? 给一个简单的序列 9 5 3 他的逆序数是3 首先要求一个逆序数有两种方式:能够从头開始往后找比当前元素小的值,也能够从后往前找比当前元素大的值,有几个逆序数就是几. 线段 ...

  6. hdu 1394 (线段树求逆序数)

    <题目链接> 题意描述: 给你一个有0--n-1数字组成的序列,然后进行这样的操作,每次将最前面一个元素放到最后面去会得到一个序列,那么这样就形成了n个序列,那么每个序列都有一个逆序数,找 ...

  7. HDU - 1394 Minimum Inversion Number (线段树求逆序数)

    Description The inversion number of a given number sequence a1, a2, ..., an is the number of pairs ( ...

  8. hdu1394 Minimum Inversion Number (线段树求逆序数&&思维)

    题目传送门 Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K ...

  9. 【线段树求逆序数】【HDU1394】Minimum Inversion Number

    题目大意: 随机给你全排列中的一个,但不断的把第一个数丢到最后去,重复N次,形成了N个排列,问你这N个排列中逆序数最小为多少 做法: 逆序数裸的是N^2 利用线段树可以降到NlogN 具体方法是插入一 ...

随机推荐

  1. Linux网络编程(附1)——封装read、write

    原打算实践简单的模型的时候,主要专注于基本的模型,先用UNIX I/O糊弄下,可是未封装的read和write用起来实在心累,还是直接用前辈们已经实现好的高级版本号read.write. UNIX I ...

  2. sql server执行动态拼接sql(带传参数)和去掉小数点后0的函数

    1 exec sp_executesql N'SELECT 2 [Extent2].[Id] AS [Id], 3 [Extent2].[Name] AS [Name], 4 [Extent2].[D ...

  3. JAVA设计模式之【建造者模式】

    建造者模式 建造者模式为客户端返回的不是一个简单的产品,而是一个由多个部件组成的复杂产品 角色 Builder抽象建造者 buildPartX getResult ConcreteBuilder具体建 ...

  4. 相辅相成的求最单源短路径算法:(SPFA& dijkstra)

    引用一位老oier的话: 一道题如果边权没有负数,那么一定是在卡SPFA.这时候就用到了堆优化的Dijkstra; 写在前面: 多打代码! 最好都掌握,灵活变通 SPFA: 主要用于稀疏图和有负权边的 ...

  5. BZOJ 1101 莫比乌斯函数+分块

    思路: 题目中的gcd(x,y)=d (x<=a,y<=b)可以转化成 求:gcd(x,y)=1 (1<=x<=a/d 1<=y<=b/d) 设 G(x,y)表示x ...

  6. css3 字体、2D转换、3D转换

    学习篇之CSS3 字体.2D转换.3D转换 一.字体 @font-face 将字体文件存放到 web 服务器上,通过CSS3 @font-face规则中定义,它会在需要时被自动下载到用户的计算机上. ...

  7. NPInter数据集的奇葩标号的出坑秘籍

    这篇恐怕是有始以来命名最无奈标题了.需要写一下攻略. 业内人士都熟知NPInter,但是该数据库一直以来访问受限.不过终于能访问得到数据集. 但是蛋疼的是2.0的数据库id的命名方法实在奇葩,想了很多 ...

  8. Servlet学习(二)——ServletContext对象

    1.什么是ServletContext对象 ServletContext代表是一个web应用的环境(上下文)对象,ServletContext对象内部封装是该web应用的信息,一个web应用只有一个S ...

  9. bat脚本启动exe并打开文件后退出 + 中文乱码

    写了个脚本用于复制模板到新的cpp文件. 将脚本路径加到环境变量里,只需在cmd窗口输入“new hdu 1419”,就会自动将模板拷贝到WORK_DIR下的hdu文件夹内一个名叫"1419 ...

  10. FCC高级编程篇之Make a Person

    Make a Person Fill in the object constructor with the following methods below: getfirstname() getLas ...