1 题目链接
2 顺序表解题思路
2.1 重要变量
- a数组:存储输入的元素
- s数组:用于记录元素加入逆序对统计过程的状态(可结合2.2的表格理解)。
- ans:记录当前逆序对的数量,初始化为0。
- ranks数组:存储输入的元素从小到大排序对应的序号。
另外还需要定义结构体node,其成员变量有num和val。a数组是node类型的。
2.2 解题过程
- 在输入n个数时,no存储输入的顺序,val存储输入的值。
- 对a数组按照元素值从小到大排序,如果遇到元素值相同的情况,则输入顺序靠前的排在前面。
- 按照输入的顺序,获取每个元素的排序编号,以输入顺序为下标,存在ranks数组中。比如对于输入的6个数,5,1,2,6,3,1,则ranks[1]=5,ranks[2]=1,ranks[3]=3,ranks[4]=6,ranks[5]=4,ranks[6]=2。
- 遍历ranks数组的每个元素,根据表达式s[ranks[i]]=1,填数,过程如下:
1)ranks[1]=5,所以s[5]=1,如下表所示。之后用变量tmp存储s[1]到s[5]填了1的格子数量,可知tmp=0。接着,我们用表达式 i - tmp表示填入第i个数位置有多少个数比第i个数大。然后将这个表达式结果加进ans中。可知当前ans = 0。
下标 | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|
数值 | 0 | 0 | 0 | 0 | 1 | 0 |
2)ranks[2]=1,所以s[1]=1,如下表所示。和1)一样,用i-tmp算出当前比第二个数大的数,表达式结果为1,更新ans的值,ans+=i-tmp=1。这里可以这样理解:如果我们把ranks里面的元素比作一群旅客住在宾馆的楼层(假设每层只住1人),每个旅客按照下标顺序入住,每个人想知道前面有多少人住的楼层比自己高,最后统计一个总和存储在ans中。对于第二个人住在1楼,他可以在上到自己的那层之前每层都去看一下,统计入住人数tmp。在这里ranks[2]=1,ranks[1]=5,所以2号旅客上到1楼入住后,他统计一下1楼之前及1楼只住了1个人,而他是第二个入住的,所以有一个人住的比他高。ans+=i-tmp=1.
下标 | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|
数值 | 1 | 0 | 0 | 0 | 1 | 0 |
3) ranks[3]=3,所以s[3]=1。同样,用2)中的例子来讲,第3个人住3楼,他也想知道有多少人住的比他高。所以在在上到自己的那层之前每层都去看一下,统计入住人数tmp=s[1]+s[2]+s[3]=2。而他是第3个入住的,所以ans+=i-tmp=2.
下标 | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|
数值 | 1 | 0 | 1 | 0 | 1 | 0 |
4) ranks[4]=6,所以s[6]=1。同样,第4个人住6楼,他也想知道有多少人住的比他高。所以在在上到自己的那层之前每层都去看一下,统计入住人数tmp=4。而他是第4个入住的,所以ans+=i-tmp=2.
下标 | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|
数值 | 1 | 0 | 1 | 0 | 1 | 1 |
5) ranks[5]=4,所以s[4]=1。同样,第5个人住4楼,他也想知道有多少人住的比他高。所以在在上到自己的那层之前每层都去看一下,统计入住人数tmp=3。而他是第5个入住的,所以ans+=i-tmp=4.
下标 | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|
数值 | 1 | 0 | 1 | 1 | 1 | 1 |
6) ranks[6]=2,所以s[2]=1。同样,第6个人住2楼,他也想知道有多少人住的比他高。所以在在上到2楼之前每层都去看一下,统计入住人数tmp=2。而他是第6个入住的,所以ans+=i-tmp=8.
下标 | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|
数值 | 1 | 1 | 1 | 1 | 1 | 1 |
按照这个过程去计算,最终样例的答案是8。
2.3 代码实现
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int s[500010],ranks[500010],n;
long long ans;
struct point
{
int num,val;
}a[