1010 Lehmer Code (35 分)(思路+详解+树状数组的学习+逆序对

/**

题目:求出某区间每一个数的和

输入格式

第一行包含两个正整数n,m,分别表示该数列数字的个数和

操作的总个数

第二行包含n个用空格分隔的整数,其中第i个数字表示数

列第i项的初始值

接下来m行每行包含3个整数,表示一个操作,具体如下

·1 x k含义:将第x个数加上k

·2 x y含义:输出区间{x,y}内每个数的和

输出格式

输出包含若干行整数,即为所有操作2的结果。

输入样例: 5 5

1 5 4 2 3

1 1 3

2 2 5

1 3 -1

1 4 2

2 1 4

输出:14

16

相关知识介绍:

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;

}

*/

#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 5

1 5 4 2 3

1 1 3

2 2 5

1 3 -1

1 4 2

2 1 4

输出:14

16

*/

//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©);

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 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 23

3 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 v1,v2;

int N;

int aa = 1;

v1.push_back(aa);

v2.push_back(aa);

memset(a,0,sizeof(a));

memset(c,0,sizeof©);

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;

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
img

总结

这份面试题几乎包含了他在一年内遇到的所有面试题以及答案,甚至包括面试中的细节对话以及语录,可谓是细节到极致,甚至简历优化和怎么投简历更容易得到面试机会也包括在内!也包括教你怎么去获得一些大厂,比如阿里,腾讯的内推名额!

某位名人说过成功是靠99%的汗水和1%的机遇得到的,而你想获得那1%的机遇你首先就得付出99%的汗水!你只有朝着你的目标一步一步坚持不懈的走下去你才能有机会获得成功!

成功只会留给那些有准备的人!

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

转存中…(img-WUMurAZ7-1712129040296)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-m1nEqjug-1712129040297)]

总结

这份面试题几乎包含了他在一年内遇到的所有面试题以及答案,甚至包括面试中的细节对话以及语录,可谓是细节到极致,甚至简历优化和怎么投简历更容易得到面试机会也包括在内!也包括教你怎么去获得一些大厂,比如阿里,腾讯的内推名额!

某位名人说过成功是靠99%的汗水和1%的机遇得到的,而你想获得那1%的机遇你首先就得付出99%的汗水!你只有朝着你的目标一步一步坚持不懈的走下去你才能有机会获得成功!

成功只会留给那些有准备的人!

[外链图片转存中…(img-XqRj9zsm-1712129040297)]

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

  • 13
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值