【树状数组专题】【蓝桥杯备考训练】:数星星、动态求连续区间和、一个简单的整数问题、一个简单的整数问题2【已更新完成】

目录

1、数星星(《信息学奥赛一本通》 & ural 1028)

思路:

基本思路:

树状数组经典三函数:

1、lowbit()函数

2、query()函数

3、add()函数

最终代码:

2、动态求连续区间和(《信息学奥赛一本通》 & 模板)

思路:

代码:

三个主要函数:

1、lowbit()函数

2、query()函数

3、add()函数

最终代码: 

3、一个简单的整数问题(《算法竞赛进阶指南》)

思路:

代码:

4、一个简单的整数问题2(POJ 2468 & 《算法竞赛进阶指南》 & kuangbin专题)

思路:

改写后的add函数:

presum函数:

最终代码:


1、数星星(《信息学奥赛一本通》 & ural 1028)

天空中有一些星星,这些星星都在不同的位置,每个星星有个坐标。

本题采用数学上的平面直角坐标系,即 x 轴向右为正方向,y 轴向上为正方向。

如果一个星星的左下方(包含正左和正下)有 k 颗星星,就说这颗星星是 k 级的。

1.png

例如,上图中星星 5 是 3 级的(1,2,4 在它左下),星星 2,4 是 1 级的。

例图中有 1 个 0 级,2 个 1 级,1 个 2 级,1 个 3 级的星星。

给定星星的位置,输出各级星星的数目。

换句话说,给定 N 个点,定义每个点的等级是在该点左下方(含正左、正下)的点的数目,试统计每个等级有多少个点。

输入格式

第一行一个整数 N,表示星星的数目;

接下来 N 行给出每颗星星的坐标,坐标用两个整数 x,y表示;

不会有星星重叠。星星按 y 坐标增序给出,y 坐标相同的按 x 坐标增序给出。

输出格式

N 行,每行一个整数,分别是 0 级,1 级,2 级,……,N−1级的星星的数目。

数据范围

1≤N≤15000
0≤x,y≤32000

输入样例:
5
1 1
5 1
7 1
3 3
5 5
输出样例:
1
2
1
1
0
思路:
基本思路:

由于x和y都是增序的,这意味每一次增加的星星都出现在原来星星的"右上方"

基于这个信息,我们可以发现对于每个星星每次都可以进行"查询",因为后插入的星星对其没有影响,快速地实现插入和查询两个操作:树状数组

查询后用一个level数组存储每个等级星星的数量(不算上自己)

最后把星星本身插入到树状数组中

树状数组经典三函数:

1、lowbit()函数
int lowbit(int x)
{return x&-x;
}
2、query()函数
int query(int x)
{//query表示查询1~x的总和int res=0;for(int i=x;i!=0;i-=lowbit(i)){res+=tree[i];}return res;
}
3、add()函数
//add表示在某一个位置加上一个数
void add(int x,int v)
{for(int i=x;i<Max;i+=lowbit(i)){tree[i]+=v;}} 
最终代码:
#include<bits/stdc++.h>
//需要快速完成两个操作 
//1、0~x中数的个数(优化:如果一个数出现过就是1,这样可以把求前缀的个数转化为求前缀和) 
//2、添加一个数x //根据特定的需求选择特定的数据结构//本题选择树状数组(可以快速支持这两个操作)(线段树也可以) 
//树状数组能操作的线段树都能操作 //树状数组的求解,下标要从1开始 
using namespace std;const int N=15000+10; const int Max=32010;//坐标最大值 int n;int level[N],tree[Max];//答案、树状数组 //树状数组的三个函数int lowbit(int x)
{return x&-x;//返回的是x的二进制表示中最后一位1 
} int query(int x)
{//query表示查询1~x的总和int res=0;for(int i=x;i!=0;i-=lowbit(i)){res+=tree[i];}return res;
}//add表示在某一个位置加上一个数
void add(int x,int v)
{for(int i=x;i<Max;i+=lowbit(i)){tree[i]+=v;}} int main()
{cin>>n;for(int i=0;i<n;i++){int x,y;scanf("%d%d",&x,&y);x++;//树状数组下标从1开始 int t=query(x);//统计一下1~x的数的总和 (也就是横坐标范围为1~x的星星的数量) level[t]++;//这个等级的星星数++; add(x,1);//把当前数加到树状数组当中 }for(int i=0;i<n;i++){printf("%d\n",level[i]);} return 0;
} 
//树状数组能快速的求前缀和O(log n)
//能快速修改某一个数O(log n) 

2、动态求连续区间和(《信息学奥赛一本通》 & 模板)

给定 n 个数组成的一个数列,规定有两种操作,一是修改某个元素,二是求子数列 [a,b] 的连续和。

输入格式

第一行包含两个整数 n 和 m,分别表示数的个数和操作次数。

第二行包含 n 个整数,表示完整数列。

接下来 m 行,每行包含三个整数 k,a,b(k=0,表示求子数列[a,b]的和;k=1,表示第 a 个数加 b)。

数列从 11 开始计数。

输出格式

输出若干行数字,表示 k=0 时,对应的子数列 [a,b]的连续和。

数据范围

1≤n≤100000
1≤m≤100000
1≤a≤b≤n
数据保证在任何时候,数列中所有元素之和均在 int 范围内。

输入样例:
10 5
1 2 3 4 5 6 7 8 9 10
1 1 5
0 1 3
0 4 8
1 7 5
0 4 8
输出样例:
11
30
35
思路:

边插入边查询就,用树状数组再合适不过了,也是标准的模板

代码:
三个主要函数:
1、lowbit()函数
int lowbit(int x)
{return x&-x;
}
2、query()函数
int query(int x)
{//query表示查询1~x的总和int res=0;for(int i=x;i!=0;i-=lowbit(i)){res+=tree[i];}return res;
}
3、add()函数
//add表示在某一个位置加上一个数
void add(int x,int v)
{for(int i=x;i<Max;i+=lowbit(i)){tree[i]+=v;}} 
最终代码: 
//树状数组中所有的奇数都和原数组相等 #include<bits/stdc++.h>using namespace std;const int Max=1e6+10;const int N=1e6+10;int tree[Max];//树状数组可以解决: 
//某个位置上的数,加上一个数---单点修改
//求某一个前缀和---区间查询 //+差分=区间修改 单点查询 || 区间修改 区间查询 //前缀和数组不支持修改,只支持查询 
//lowbit(x)=2**k(k为末尾连续0的个数) // 树状数组每个位置存的都是原数组一段数的和(从x-lowbit(x)到x)
//c[x]=value[x-lowbit(x) ,x]     //树状数组的三个操作 
int lowbit(int x)
{return x&-x;
}int query(int x)
{int res=0;for(int i=x;i;i-=lowbit(i)){res+=tree[i];}return res;
}int add(int x,int v)//在某一个位置x加上v (会影响到后面的树根,所以有如下写法) 
{for(int i=x;i<=Max;i+=lowbit(i)){tree[i]+=v;}
}int main()
{int n,m;scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){int v;scanf("%d",&v);add(i,v);}while(m--){int op,a,b;scanf("%d%d%d",&op,&a,&b);if(op==0){int res=query(b)-query(a-1);printf("%d\n",res);}else{add(a,b);}}return 0;
} 

3、一个简单的整数问题(《算法竞赛进阶指南》)

给定长度为 N 的数列 A,然后输入 M 行操作指令。

第一类指令形如 C l r d,表示把数列中第 l∼r个数都加 d。

第二类指令形如 Q x,表示询问数列中第 x 个数的值。

对于每个询问,输出一个整数表示答案。

输入格式

第一行包含两个整数 N 和 M。

第二行包含 N 个整数 A[i]。

接下来 M 行表示 M 条指令,每条指令的格式如题目描述所示。

输出格式

对于每个询问,输出一个整数表示答案。

每个答案占一行。

数据范围

1≤N,M≤1e5
|d|≤10000
|A[i]|≤1e9

输入样例:
10 5
1 2 3 4 5 6 7 8 9 10
Q 4
Q 1
Q 2
C 1 6 3
Q 2
输出样例:
4
1
2
5
思路:

树状数组+差分的应用:差分使得树状数组由单点修改+区间查询进化为了:区间修改+单点查询

经典三操作不变,只是求出来的和变成了原数组而已

代码:
  //树状数组中所有的奇数都和原数组相等 #include<bits/stdc++.h>using namespace std;const int Max=1e6+10;const int N=1e6+10;int tree[Max];//树状数组可以解决: 
//某个位置上的数,加上一个数---单点修改
//求某一个前缀和---区间查询 //+差分=区间修改 单点查询 || 区间修改 区间查询 //前缀和数组不支持修改,只支持查询 
//lowbit(x)=2**k(k为末尾连续0的个数) // 树状数组每个位置存的都是原数组一段数的和(从x-lowbit(x)到x)
//c[x]=value[x-lowbit(x) ,x]     //树状数组的三个操作 
int lowbit(int x)
{return x&-x;
}int query(int x)
{int res=0;for(int i=x;i;i-=lowbit(i)){res+=tree[i];}return res;
}int add(int x,int v)//在某一个位置x加上v (会影响到后面的树根,所以有如下写法) 
{for(int i=x;i<=Max;i+=lowbit(i)){tree[i]+=v;}
}int main()
{int n,m;scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){int v;scanf("%d",&v);add(i,v);}while(m--){int op,a,b;scanf("%d%d%d",&op,&a,&b);if(op==0){int res=query(b)-query(a-1);printf("%d\n",res);}else{add(a,b);}}return 0;
} 

4、一个简单的整数问题2(POJ 2468 & 《算法竞赛进阶指南》 & kuangbin专题)

给定一个长度为 N 的数列 A,以及 M 条指令,每条指令可能是以下两种之一:

  1. C l r d,表示把 A[l],A[l+1],…,A[r]都加上 d。
  2. Q l r,表示询问数列中第 l∼r个数的和。

对于每个询问,输出一个整数表示答案。

输入格式

第一行两个整数 N,M。

第二行 N 个整数 A[i]。

接下来 M 行表示 M 条指令,每条指令的格式如题目描述所示。

输出格式

对于每个询问,输出一个整数表示答案。

每个答案占一行。

数据范围

1≤N,M≤1e5
|d|≤10000
|A[i]|≤1e9

输入样例:
10 5
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
C 3 6 3
Q 2 4
输出样例:
4
55
9
15
思路:

树状数组+差分

这里需要一个小小的推导,最后得出公式:

Sn=(∑bi) * (n+1) - (∑(i*bi))) 记住即可

为了实现这个公式,维护两个数组,一个是差分树状数组tr1,另一个是存储i*tr[i]的树状差分数组

由于要为两个数组进行add操作,所以我们改写add函数(加一个参数)

改写后的add函数:
void add(LL tr[],int x,LL v)
{for(int i=x;i<=n;i+=lowbit(i)){tr[i]+=v;	}	
} 

为了实现公式,我们写出求Sn的函数:

presum函数:
LL presum(int x)//求前缀和Sx(x及之前的和) (Sn=(∑bi) * (n+1) - (∑(i*bi))) 
{LL a = query(tr1,x)*(x+1);LL b=query(tr2,x);return a-b;
}
最终代码:
#include<bits/stdc++.h>using namespace std;const int N=1e5+10;typedef long long LL;int a[N];//a是原数组 LL tr1[N];//维护b【i】的前缀和 LL tr2[N];//维护i*b【i】的前缀和int n,m; int lowbit(int x)
{return x&-x;
}//这里因为要处理两个数组,所以加上数组参数
void add(LL tr[],int x,LL v)
{for(int i=x;i<=n;i+=lowbit(i)){tr[i]+=v;	}	
} LL query(LL tr[],int x)
{LL res=0;for(int i=x;i;i-=lowbit(i)){res+=tr[i];}return res;
}LL presum(int x)//求前缀和Sx(x及之前的和) (Sn=(∑bi) * (n+1) - (∑(i*bi))) 
{LL a = query(tr1,x)*(x+1);LL b=query(tr2,x);return a-b;
}int main()
{cin>>n>>m;for(int i=1;i<=n;i++)scanf("%d",&a[i]);//形成树状差分数组 for(int i=1;i<=n;i++){int b=a[i]-a[i-1];add(tr1,i,b);add(tr2,i,(LL)b*i);}	while(m--){char op[1];scanf("%s",op);if(op[0]=='C'){int l,r,v;scanf("%d%d%d",&l,&r,&v);//b[l]+=v b[r+1]-=vadd(tr1,l,v);add(tr1,r+1,-v);//b[l]+=l*v b[r+1]-=l*vadd(tr2,l,(LL)l*v);add(tr2,r+1,(LL)-(r+1)*v);}else{int l,r;scanf("%d%d",&l,&r);cout<<presum(r)-presum(l-1)<<endl;}}return 0;
} 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/295381.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java电话号码的字母组合(力扣Leetcode17)

电话号码的字母组合 力扣原题链接 问题描述 给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下&#xff08;与电话按键相同&#xff09;。注意 1 不对应任何字母。 示例 示例 1&#xff1a;…

【Web】记录Polar靶场<困难>难度题一遍过

目录 上传 PHP是世界上最好的语言 非常好绕的命令执行 这又是一个上传 网站被黑 flask_pin veryphp 毒鸡汤 upload tutu Unserialize_Escape 自由的文件上传系统​​​​​​​ ezjava 苦海 你想逃也逃不掉 safe_include CB链 phar PHP_Deserializatio…

算法整理:二分查找

1二分查找&#xff1a;在有序集合搜索特定值的过程&#xff0c;每次比较之后将查找空间一分为二。 target:要查找的值 index:当前位置 left,right:维持查找空间的指标 mid:用来确定向左查还是向右查的索引 查找空间: [left,right] 二分查找维护left&#xff0c;right&#xff0…

QA测试开发工程师面试题满分问答4: 如何测试购物车功能?

当测试一个购物车时&#xff0c;我们需要采用全面的测试策略&#xff0c;以确保购物车在各种情况下的功能正常、性能良好和用户体验优秀。以下是一个详细的测试计划&#xff0c;包含了各个方面的测试。 功能测试&#xff1a; 添加商品到购物车&#xff1a;验证能否将商品成功添…

【算法集训】基础算法:前缀和 | 概念篇

前缀和就是对于顺序表&#xff08;数组、列表&#xff09;来说&#xff0c;计算前面某一段元素的和。 1、部分和 给定一个数组&#xff0c;求某一段子数组的和。 2、朴素做法 int partialSum(int *a, int l, int r) {int i;int s 0;for(i l; i < r; i) {s a[i];}retu…

华为交换机配置指引(包含安全配置部分)以 S5735S-L48T4S-A1 配置为例

华为S5735S-L48T4S-A1 是一款千兆以太网交换机: 端口结构: 48个10/100/1000BASE-T以太网端口和4个千兆SFP光接口供电方式: 交流电源背板带宽: 432Gbps包转发率: 87/166Mpps机箱高度: 1U重量: 2.76kg(不含包材)功耗: 典型功耗为43.3W接口: 48个10/100/1000BASE-T以太网电接口…

图论做题笔记:dfs

Leetcode - 797&#xff1a;所有可能的路径 题目&#xff1a; 给你一个有 n 个节点的 有向无环图&#xff08;DAG&#xff09;&#xff0c;请你找出所有从节点 0 到节点 n-1 的路径并输出&#xff08;不要求按特定顺序&#xff09; graph[i] 是一个从节点 i 可以访问的所有节…

【C++】哈希之位图

目录 一、位图概念二、海量数据面试题 一、位图概念 假如有40亿个无重复且没有排序的无符号整数&#xff0c;给一个无符号整数&#xff0c;如何判断这个整数是否在这40亿个数中&#xff1f; 我们用以前的思路有这些&#xff1a; 把这40亿个数遍历一遍&#xff0c;直到找到为…

大话设计模式之外观模式

外观模式&#xff08;Facade Pattern&#xff09;是一种软件设计模式&#xff0c;旨在提供一个简单的接口&#xff0c;隐藏系统复杂性&#xff0c;使得客户端能够更容易地使用系统。这种模式属于结构型模式&#xff0c;它通过为多个子系统提供一个统一的接口&#xff0c;简化了…

全志 Linux Qt

一、简介 本文介绍基于 buildroot 文件系统的 QT 模块的使用方法&#xff1a; • 如何在 buildroot 工具里编译 QT 动态库&#xff1b; • 编译及运行 qt_demo 应用程序&#xff1b; • 适配过程遇到的问题。 二、QT动态库编译 在项目根路径执行 ./build.sh buildroot_menuc…

AI 论道|极狐GitLab 客户私享会上海站成功举办

3 月 22 日下午&#xff0c;极狐GitLab 在上海办公室举办了客户私享会&#xff0c;邀请了来自多个行业的多家客户&#xff0c;围绕 AI 提升研发效率的道法术器进行了充分交流。整个交流时长达两个多小时。 极狐GitLab 战略业务与区域发展副总裁何庆出席了此次活动并致开场辞。他…

Spring IOC控制反转、DI注入以及配置

1.使用xml的方式进行配置IOC容器&#xff0c;首先引入依赖 在Resource资源下配置&#xff0c;applicationContext.xml ,刷新mevan后可以直接选择配置spring.xml文件 <!-- spring核心用来管理bean --><dependency><groupId>org.springframework</g…

Netty入门

二. Netty 入门 1. 概述 1.1 Netty 是什么&#xff1f; Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty 是一个异步的、基于事件驱动的网络应用框架&…

Python-VBA编程500例-029(入门级)

连续字符段索引(Index of Consecutive Character Segments)在实际应用中具有多种场景。常见的应用场景有&#xff1a; 1、文本分析&#xff1a;在文本处理和分析中&#xff0c;连续字符段索引可以用于识别重复的字符序列或模式。这些模式可能对于理解文本的结构、风格或特定含…

使用docker部署MongoDB数据库

最近由于工作需要搭建MongoDB数据库&#xff1a;将解析的车端采集的数据写入到数据库&#xff0c;由于MongoDB高可用、海量扩展、灵活数据的模型&#xff0c;因此选用MongoDB数据库&#xff1b;由于现公司只有服务器&#xff0c;因此考虑容器化部署MongoDB数据&#xff0c;特此…

制造业工厂怎么通过MES系统来升级改造车间管理

在当今高度竞争的市场环境下&#xff0c;制造业企业需要不断提高生产效率&#xff0c;以在激烈的竞争中立于不败之地。而一种被广泛应用的方法就是利用MES控制系统&#xff0c;通过数字化管理和自动化控制来改造生产车间提升生产效率。 1、MES管理系统能够实现对生产过程的全面…

HarmonyOS 和 OpenHarmony

HarmonyOS 和 OpenHarmony 支持的 shell 命令不同&#xff0c;因此有时候需要做一做区分&#xff0c;目前有些文档上没有标注&#xff0c;因此可能产生歧义。 HarmonyOS 支持 getprop&#xff1a; getprop hw_sc.build.os.apiversion # 查看API版本OpenHarmony 上支持 param…

158 Linux C++ 通讯架构实战13,epoll 原理和函数介绍,epoll_create,epoll_ctl ,epoll_wait

epoll技术简介 //&#xff08;2.1&#xff09;epoll概述 //(1)I/O多路复用&#xff1a;epoll就是一种典型的I/O多路复用技术:epoll技术的最大特点是支持高并发&#xff1b; //传统多路复用技术select,poll&#xff0c;在并发量达到1000-2000&#xff0c;性能就会明显下…

YOLOV5 改进:更换主干网络为Resnet

1、前言 之前实现了yolov5更换主干网络为MobileNet和vgg网络 本章将继续将yolov5代码进行更改,通过引用官方实现的resnet网络,替换原有的yolov5主干网络 替换的效果如下: 2、resnet 网络结构 测试的代码为官方的resnet34 通过summary 打印的resnet网络结构如下 =======…

【Linux】Vim编辑器

专栏文章索引&#xff1a;Linux 目录 在Vim编辑器中&#xff0c;一个Tab键相当于几个空格&#xff1f; 在Vim编辑器中&#xff0c;一个Tab键相当于几个空格&#xff1f; 在Vim编辑器中&#xff0c;默认情况下&#xff0c;一个Tab键相当于8个空格。 这是Vim的默认设置&#x…