一:题目

According to Wikipedia: “In mathematics and in particular in combinatorics, the Lehmer code is a particular way to encode each possible permutation of a sequence of n numbers.” To be more specific, for a given permutation of items {A

}, Lehmer code is a sequence of numbers {L hat L is the total number of items from Ato A which are less than A
. For example, given { 24, 35, 12, 1, 56, 23 }, the second Lehmer code L 2 is 3 since from 35 to 23 there are three items, { 12, 1, 23 }, less than the second item, 35.

Input Specification:
Each input file contains one test case. For each case, the first line gives a positive integer N (≤10
5
). Then N distinct numbers are given in the next line.

Output Specification:
For each test case, output in a line the corresponding Lehmer code. The numbers must be separated by exactly one space, and there must be no extra space at the beginning or the end of the line.

Sample Input:

6
24 35 12 1 56 23

结尾无空行
Sample Output:

3 3 1 0 1 0

二:思路:

这个题用到的是树状数组的相关知识 ,其中在树状数组的应用当中有求逆序对一项,但这个题不能直接用,这个题并没有给出 输入的数字的范围 那就无法直接用 求逆序对的方法来求,
因为会出现段错误(因为输入的数 可能大于 500000)
但是我们可以将输入的数进行转换,将他们先进行排序,将他们的下标作为他们的
代替,这样我们就控制住输入数字的范围了,这个题也已经明确指出了输入数字
不重复,所以我们可以大胆的用map,来记录他们的排序

这里举例来说明我们用排好序的下标来代替数,这样控制住数的范围,且结果一样:

我们可以看到 第一个数 4,4后面比其小的数 还是有 3 个;

三:上码:


/**思路:这个题并没有给出 输入的数字的范围 那就无法直接用 求逆序对的方法来求因为会出现段错误(因为输入的数 可能大于 500000) 但是我们可以将输入的数进行转换,将他们先进行排序,将他们的下标作为他们的代替,这样我们就控制住输入数字的范围了,这个题也已经明确指出了输入数字不重复,所以我们可以大胆的用map,来记录他们的排序 */ #include<bits/stdc++.h>
using namespace std;int c[100005];int lowbit(int x){return x&(-x);
}//单点更新
void update(int x,int y,int n){while(x <= n){c[x] =  c[x] + y;x = x + lowbit(x);        }} //求取前缀和
int getSum(int pos){int sum = 0;while(pos > 0){sum += c[pos];pos = pos - lowbit(pos);  }return sum;
} int main(){int a[100005];vector<int> v1,v2,v3;map<int,int>m; int N;memset(a,0,sizeof(a));memset(c,0,sizeof(c));cin >> N;for(int i = 0; i < N; i++){int temp;cin >> temp;a[i] = temp;v1.push_back(temp);}sort(v1.begin(),v1.end()); for(int i = 0; i < N; i++){m[v1[i]] = i + 1;}for(int i = N - 1; i >= 0; i--){int num = m[a[i]];       update(num,1,100005);//这里求的是getSum(temp) 表示的是前面比 temp小的个数其中是包含temp本身的 int temp = getSum(num) - 1;v2.push_back(temp);}for(int i = N-1; i >= 0; i--){if(i == N - 1){cout << v2[i];}else{cout << ' ' << v2[i]; }}
}

四:介绍相关的知识

1:树状数组

(1):图示:

(2):相关的介绍

相关知识介绍:
1.理解图 A[i]:表示的是正常的数组
C[i]:表示的是区间的和

eg: c[1] =A[1]
c[2] = A[1] + A[2]
c[6] = A[5] + A[6]

2.那么如何表示C[i] 中 i表示的个数呢 这时候要用到lowbit(i),
lowbit(i) = i & (-i)

eg:lowbit(6) = 2
lowbit(4) = 4

3.i + lowbit[i]:表示其父亲结点的下标
eg:6 + lowbit(6) = 8

i - lowbit(i):表示其左边管辖区域的下标
eg:6 - lowbit(6) = 4

4.相关的函数
(1):求取lowbit(i)

int lowbit (int i){return i & (-i);
}

(2):更新单点的值,就是如果你给区间内的某个值增加一定的数,那么其父节点
也会增加相应的值
eg: A[1]比以前大了,那么C[1]也要比以前的大,他的父节点C[2],
也要跟着变大,那么的话,c[2]的父节点也要跟着变大

void update(int x,int y,int n){//参数:表示在x位置增加了y 数组长度为n

while(x <= n){c[x] = c[x] + y;
x = x + lowbit(x);//求取父节点
}   }

(3):求前缀和
eg:求取前6个数的和
sum[6] = A[1] + A[2] + A[3]+ A[4]+ A[5] + A[6]

因为:C[6] = A[5] + A[6]
C[4] = A[1]+A[2]+A[3]+A[4]
那么也就是sum[6] = C[6] + C[4]

int getSum(int pos){int sum = 0;while(pos > 0){sum += C[pos]pos = pos - lowbit[pos]
}return sum;
}

2:例题求取区间和

 题目:求出某区间每一个数的和输入格式第一行包含两个正整数n,m,分别表示该数列数字的个数和操作的总个数第二行包含n个用空格分隔的整数,其中第i个数字表示数列第i项的初始值接下来m行每行包含3个整数,表示一个操作,具体如下·1 x k含义:将第x个数加上k·2 x y含义:输出区间{x,y}内每个数的和输出格式输出包含若干行整数,即为所有操作2的结果。输入样例: 5 51 5 4 2 31 1 32 2 51 3 -11 4 22 1 4输出:1416
/**题目:求出某区间每一个数的和输入格式第一行包含两个正整数n,m,分别表示该数列数字的个数和操作的总个数第二行包含n个用空格分隔的整数,其中第i个数字表示数列第i项的初始值接下来m行每行包含3个整数,表示一个操作,具体如下·1 x k含义:将第x个数加上k·2 x y含义:输出区间{x,y}内每个数的和输出格式输出包含若干行整数,即为所有操作2的结果。输入样例: 5 51 5 4 2 31 1 32 2 51 3 -11 4 22 1 4输出:1416相关知识介绍:1.理解图 A[i]:表示的是正常的数组C[i]:表示的是区间的和 eg:  c[1] =A[1]c[2] = A[1] + A[2]c[6] = A[5] + A[6]2.那么如何表示C[i] 中 i表示的个数呢 这时候要用到lowbit(i),lowbit(i) = i & (-i)eg:lowbit(6) = 2lowbit(4) = 43.i + lowbit[i]:表示其父亲结点的下标eg:6 + lowbit(6) = 8i - lowbit(i):表示其左边管辖区域的下标eg:6 - lowbit(6) = 44.相关的函数(1):求取lowbit(i)int lowbit (int i){return i & (-i);}   (2):更新单点的值,就是如果你给区间内的某个值增加一定的数,那么其父节点也会增加相应的值eg: A[1]比以前大了,那么C[1]也要比以前的大,他的父节点C[2],也要跟着变大,那么的话,c[2]的父节点也要跟着变大void update(int x,int y,int n){//参数:表示在x位置增加了y 数组长度为nwhile(x <= n){c[x] = c[x] + y;x = x + lowbit(x);//求取父节点 } }(3):求前缀和eg:求取前6个数的和sum[6] = A[1] + A[2] + A[3]+ A[4]+ A[5]    + A[6]因为:C[6] = A[5] + A[6]C[4] = A[1]+A[2]+A[3]+A[4] 那么也就是sum[6] = C[6] + C[4] int getSum(int pos){int sum = 0;while(pos > 0){sum += C[pos]pos = pos - lowbit[pos]}return sum;}*/#include<bits/stdc++.h>
using namespace std;int c[1000] = {0};int lowbit(int x){return x&(-x);
}//更新单节点
void update(int x,int y,int n){while(x <= n){c[x] = c[x] + y;x = x + lowbit(x);}
}//求前缀和
int getSum(int pos){int sum = 0;while(pos > 0){sum += c[pos];pos = pos - lowbit(pos);    }return sum;
} int main(){int N,M;int a[1000];memset(a,0,sizeof(a));cin >> N >> M;for(int i = 1; i <= N; i++){cin >>a[i];//这里就是往C[i]中赋值的操作,因为初始的a[i]中的值均为0,故可以开始更新 update(i,a[i],N); }for(int i = 0; i < M; i++){int operation,num1,num2;cin >> operation >> num1 >> num2;if(operation == 1){update(num1,num2,N);}else if(operation == 2){cout << getSum(num2) - getSum(num1-1) << endl;}else{cout << "您的输入有误!!"; } }//测试数据
//  for(int i = 1; i <= N; i++){//      cout << c[i] << ' ';
//  } //    cout << a[99];} /**·1 x k含义:将第x个数加上k·2 x y含义:输出区间{x,y}内每个数的和输出格式输出包含若干行整数,即为所有操作2的结果。输入样例: 5 51 5 4 2 31 1 3           2 2 51 3 -11 4 22 1 4输出:1416
*///5 5
//1 5 4 2 3
//1 1 3
//2 2 5
//1 3 -1
//1 4 2
//2 1 4

3:求逆序对

何为逆序对:
什么是逆序对
设A为一个有n个数字的有序集(>1),其中所有数字各不相同。如果存在正整数i,j
使得1<=i<j<=n而且A[i]>A[j],则<A[i],A[j]>这个有序对称为A的一个逆序对,也称作逆序数。例如
数组(3 1 4 5 2)的逆序对有(3,1)(32)(42)(5,2),共4个

思路:输入的N个数 3 1 4 5 2
每次输入的值都在 A[i](i = 输入的值) 对应的位置 A[3] = 1,A[1] = 1;
其中A[] ,C[],初始化均为0,每次a[i]变化对应的更新C[i]的值
那么前面比其大的数的个数 = i - (前面比其小的个数)
= i - getSum(a[i])


/**何为逆序对:什么是逆序对设A为一个有n个数字的有序集(>1),其中所有数字各不相同。如果存在正整数i,j使得1<=i<j<=n而且A[i]>A[j],则<A[i],A[j]>这个有序对称为A的一个逆序对,也称作逆序数。例如数组(3 1 4 5 2)的逆序对有(3,1)(32)(42)(5,2),共4个 思路:输入的N个数 3 1 4 5 2每次输入的值都在 A[i](i = 输入的值) 对应的位置  A[3] = 1,A[1] = 1;其中A[] ,C[],初始化均为0,每次a[i]变化对应的更新C[i]的值那么前面比其大的数的个数 = i - (前面比其小的个数)=    i - getSum(a[i]) */ #include<bits/stdc++.h>
using namespace std;int c[1000];int lowbit(int x){return x&(-x);
}//单点更新
void update(int x,int y,int n){while(x <= n){c[x] =  c[x] + y;x = x + lowbit(x);        }} //求取前缀和
int getSum(int pos){int sum = 0;while(pos > 0){sum += c[pos];pos = pos - lowbit(pos);  }return sum;
} int main(){int a[1000],b[1000];int N;memset(a,0,sizeof(a));memset(b,0,sizeof(b));memset(c,0,sizeof(c));cin >> N;for(int i = 1; i <= N; i++){int temp;cin >> temp;a[temp] = 1;update(temp,a[temp],1000);//这里求的是getSum(temp) 表示的是前面比 temp 小的个数 cout << i - getSum(temp) << ' ';   }}

4:对map和vector容器 不熟练的兄弟们可以看下这个连接

map的基本用法
vector的基本用法

五:学习记录

这个题做了3个晚上,从刚拿到直接做,到后来 开始学习树状数组,求区间和,逆序对,慢慢组成了这道题的题解

第一次做的代码:过去俩点


#include<bits/stdc++.h>
using namespace std;int main(){int N;vector<int> v1,v2;cin >> N;for(int i = 0; i < N; i++){int temp;cin >> temp;    v1.push_back(temp);}for(int i = 0; i < N; i++){int count = 0;for(int j = i+1; j < N; j++){if(v1[i] > v1[j]){count++;}}v2.push_back(count);}int flag = 0;for(int i = 0; i < N; i++){if(flag == 0){cout << v2[i];}else{cout << ' ' << v2[i];}flag = 1;}} /**
6
24 35 12 1 56 233 3 1 0 1 0*/

第二次做的代码,过去4个点但是其还是有一个点超时


#include<bits/stdc++.h>
using namespace std;int c[1000005];int lowbit(int x){return x&(-x);
}//单点更新
void update(int x,int y,int n){while(x <= n){c[x] =  c[x] + y;x = x + lowbit(x);        }} //求取前缀和
int getSum(int pos){int sum = 0;while(pos > 0){sum += c[pos];pos = pos - lowbit(pos);  }return sum;
} int main(){int a[1000005],b[10000];vector<int> v1,v2;int N;int aa = 1;v1.push_back(aa);v2.push_back(aa);memset(a,0,sizeof(a));memset(c,0,sizeof(c));cin >> N;for(int i = 1; i <= N; i++){int temp;cin >> temp;v1.push_back(temp);}for(int i = N; i >= 1; i--){int num = v1[i];a[num] = 1;update(num,a[num],1000005);//这里求的是getSum(temp) 表示的是前面比 temp小的个数其中是包含temp本身的 int temp = getSum(num) - 1;v2.push_back(temp);}for(int i = N; i >= 1; i--){if(i == N){cout << v2[i];}else{cout << ' ' << v2[i]; }}}

加油 陌生人 ,学习就是就像分治算法一样,将一个大问题分解成小问题,然后逐个解决,最后的结果合并成大问题的解,

1010 Lehmer Code (35 分)(思路+详解+树状数组的学习+逆序对+map+vector) 超级详细 Come baby!!!相关推荐

  1. [蓝桥杯][算法提高VIP]分苹果(差分||树状数组)

    题目描述 小朋友排成一排,老师给他们分苹果. 小朋友从左到右标号1-N.有M个老师,每次第i个老师会给第Li个到第Ri个,一共Ri-Li+1个小朋友每人发Ci个苹果. 最后老师想知道每个小朋友有多少苹 ...

  2. P4062 [Code+#1]Yazid 的新生舞会 树状数组维护三阶差分

    传送门 文章目录 题意: 思路: 题意: 给你一个序列aaa,让你求有多少个子区间满足存在一个数是这个区间的绝对众数,绝对众数指该数在区间内出现的次数严格大于r−l+12\frac{r-l+1}{2} ...

  3. Linux 目录详解 树状目录结构图

    1.树状目录结构图 2./目录 目录 描述 / 第一层次结构的根.整个文件系统层次结构的根目录. /bin/ 需要在单用户模式可用的必要命令(可执行文件):面向所有用户,例如:cat.ls.cp,和/ ...

  4. 10-4 6-4 查询厂商“D“生产的PC和便携式电脑的平均价格 (10 分)思路+详解+测试用例

    前言:测试用表 贴心杰将这个测试表分享给大家 ,如果大家做题的时候发现那个点过不去,一定不要直接看别人的博客,先自己测试用例,如果思路也对 ,验证数据也对,还有错误 你再看看别人的思路!!! CREA ...

  5. 7-3 符号三角形 (10 分)(思路+详解)

    一:题目 Come 宝 !!! 输入格式: 第一行符号个数n 输出格式: 符合要求的三角形个数 输入样例: 4 结尾无空行 输出样例: 6 二:思路 思路: 1.如果我们确立的第一行的符号是什么 ,那 ...

  6. 7-1 装载问题 (10 分)(思路+详解)

    一:题目 Come 宝宝!! 输出格式: 输出所有可行的方案数量 输入样例1: 3 50 50 10 40 40 结尾无空行 输出样例1: 4 结尾无空行 输入样例2: 3 50 50 20 40 4 ...

  7. 7-4 N皇后 (28 分)(思路+详解)

    一:题目 Come 宝!!!!!!!!!!!! 在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上. 你的任务是,对于 ...

  8. 7-8 数字三角形 (31 分)(思路+详解+动态规划)Come Baby!!!!!!!!!!!

    一:题目 观察下面的数字金字塔.写一个程序查找从最高点到底部任意处结束的路径,使路径经过数字的和最大.每一步可以从当前点走到左下方的点也可以到达右下方的点. 在上面的样例中,从13到8到26到15到2 ...

  9. 7-1 矩阵链相乘问题 (20 分)(思路+详解+题目解析) 动态规划做法

    一:题目: 输入样例: 在这里给出一组输入.例如: 5 30 35 15 5 10 20 输出样例: 在这里给出相应的输出.例如: 11875 二:基本解析 1.基本的动态规划知识: 1):求解过程是 ...

最新文章

  1. uiautomator环境搭建所遇问题汇总
  2. c#读取xml文件配置文件Winform及WebForm-Demo具体解释
  3. selenium python怎么读_selenium+Python中的面试总结
  4. python integer_【Python】string/list/integer常用函数总结
  5. boost::mp11::mp_unique_if相关用法的测试程序
  6. JavaScript中this指向
  7. 数据结构---平衡二叉树
  8. 【Loj - 515】贪心只能过样例(暴力,或01背包 + bitset)
  9. java 调用宏_通过java代码实现调用excel当中的宏的操作。
  10. 电影的幕布效果怎么做?
  11. Android 关于display的几个问题
  12. 《Qt5 Cadaques》学习笔记(六):QT QUICK Controls 2
  13. Avalonia UI 简介
  14. instandceof
  15. 电子束光刻胶(HSQXR-1541-006,mr-I 9000M)
  16. 专访STEM领域人才资深人工智能图像算法工程师张旦
  17. centos7克隆虚拟机
  18. Linux网络管理员面试题
  19. 【论文翻译】Deep Residual Learning for Image Recognition
  20. 基于Visual Graph快速开发出电力系统

热门文章

  1. Entity Framework升级
  2. C#读书雷达 | TW洞见
  3. slider控件控制文本框字体大小
  4. Flutter之运行提示Could not update files on device: Connection closed before full header was received
  5. React Native之Props(属性)和State(状态)和简单样式简单使用
  6. IOS学习笔记之十七 (NSDate、NSDateFormatter、NSCalendar、NSDateComponents、NSTimer)
  7. Android之OKHttp使用总结
  8. 【iVX 初级工程师培训教程 10篇文拿证】03 事件及猜数字小游戏
  9. 【C语言简单说】十四:for循环
  10. 这些让人看瞎了的设计!实力证明,谁才是世界的最终boss!