P3368 【模板】树状数组 2
原题链接 https://www.luogu.org/problemnew/show/P3368



这个题和洛谷P3374树状数组1 有些不同,在普通的树状数组上运用了差分的知识。(由于P3374涉及到一些较为基础的知识,就先不讲了,反正大家都会了QwQ~);
什么是差分呢?
差分差分,顾名思义就是相差的分数啦 ,其实就是每一项与前一项的差距,通常我们用d数组来表示。
举个例子,假如我们有一个序列:
a1=1,a2=5,a3=6,a4=3,a5=4;
那么可以计算出每一项的差分:
d1=a1 - a0 =1 - 0 = 1;(第一项的差分就是原数)
d2=a2 - a1 =5 - 1 = 4;
d3=a3 - a2 =6 - 5 = 1;
d4=a4 - a3 =3 - 6 = -3;
d5=a5 - a4 =4 - 3 = 1;
有的小盆友就要问了:知道这个差分有啥用嘞?
这是树状数组“区间修改,单点查询”的关键!
考虑一个简单的小问题:知道了d1~5,怎么求a5?
It is so easy !
a5 = a4 + d5 = a3 + d4 + d5 = a2 + d3 + d4 + d5 = a1 + d2 + d3 + d4 + d5 = d1 + d2 + d3 + d4 + d5 ;
也就是说,an= d1 + d2 + d3 + ……+ dn;
这一看不就是差分数组的前缀和嘛?正好我们可以用树状数组来维护前缀和:
void add(int x,int k) //在第x个数上加个k
{
for(int i=x;i<=n;i+=lowbit(i)) c[i]+=k;
}
int ask(int x) //询问区间[1,x]的和
{
int ans=;
for(int i=x;i;i-=lowbit(i))
ans+=c[i];
return ans;
}
又有小盆友来问了:不是你是用原数组求得差分,再用差分求回去,干啥嘞?只为了用树状数组维护前缀和?直接输出 a [ n ] 不好嘛?
其实这只是为了区间修改方便!
普通(暴力)区间修改思路:
for循环从l~r暴力枚举每个点然后加上某个值,最差的时间复杂度是O(q * n2),q是操作次数,这显然会TLE;
但是我们用了差分以后就不一样了,考虑一下区间修改后对差分数组的影响:
原先:
a: 1 5 6 3 4
d: 1 4 1 -3 1
在区间[3,5]上每个数都加上2:
a: 1 5 8 5 6
d: 1 4 3 -3 1
一个很显然的结论:对于修改的区间[ l,r ],让这个区间内每个数加上x,对于差分数组d其实就是d[ l ] 加上x,d [ r + 1 ] 减去x(不懂的看上面的例子感性理解下);
所以我们只需要用树状数组维护两次前缀和就好啦!
完整代码如下:
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int read()
{
char ch=getchar();
int a=,x=;
while(ch<''||ch>'')
{
if(ch=='-') x=-x;
ch=getchar();
}
while(ch>=''&&ch<='')
{
a=(a<<)+(a<<)+(ch-'');
ch=getchar();
}
return a*x;
}
int n,m,x,y,k,q;
int a[],d[],c[];
int lowbit(int x)
{
return x&(-x);
}
void add(int x,int k) //在第x个数上加个k
{
for(int i=x;i<=n;i+=lowbit(i)) c[i]+=k; //加上lowbit去找它的父亲
}
int ask(int x) //询问区间[1,x]的和
{
int ans=;
for(int i=x;i;i-=lowbit(i)) //区间长度不断缩小
ans+=c[i];
return ans;
}
int main()
{
n=read();m=read(); //n个数,m次操作
for(int i=;i<=n;i++)
{
a[i]=read();
d[i]=a[i]-a[i-]; //算出每一项的差分是多少
add(i,d[i]); //注意这里维护的是差分数组
}
for(int i=;i<=m;i++)
{
q=read();
if(q==)
{
x=read();y=read();k=read(); //[x,y]加上k
add(x,k); //左端点差分+k
add(y+,-k); //右端点的右边的差分-k
}
else
{
x=read();
printf("%d\n",ask(x)); //差分前缀和,就是某一项的值
}
}
return ;
}
P3368 【模板】树状数组 2的更多相关文章
- [模板] 树状数组 (C++ class)
闲来无事(其实是打了两三道树状数组题),写了个树状数组模板…… /* Author: hotwords */ template<typename tp> class BinTree { p ...
- HDU 1166 线段树模板&树状数组模板
HDU1166 上好的线段树模板&&树状数组模板 自己写的第一棵线段树&第一棵树状数组 莫名的兴奋 线段树: #include <cstdio> using nam ...
- 【洛谷 p3368】模板-树状数组 2(数据结构)
题目:已知一个数列,你需要进行下面两种操作:1.将某区间每一个数数加上x:2.求出某一个数的和. 解法:树状数组+前缀和优化.数组中每位存和前一位的数的差,这样区间修改只用改两位,单点询问就是求前缀和 ...
- 【洛谷 p3374】模板-树状数组 1(数据结构)
题目:已知一个数列,你需要进行下面两种操作:1.将某一个数加上x:2.求出某区间每一个数的和. 解法:树状数组求前缀和. #include<cstdio> #include<cstd ...
- POJ2299逆序对模板(树状数组)
题目:http://poj.org/problem?id=2299 只能相邻两个交换,所以交换一次只会减少一个逆序对.所以交换次数就是逆序对数. ps:原来树状数组还可以记录后边lowbit位的部分和 ...
- 洛谷.3374.[模板]树状数组1(CDQ分治)
题目链接 简易CDQ分治教程 //每个操作分解为一个有序数对(t,p),即(时间,操作位置),时间默认有序,用CDQ分治处理第二维 //对于位置相同的操作 修改优先于查询 //时间是默认有序的 所以可 ...
- 【poj 3167】Cow Patterns(字符串--KMP匹配+数据结构--树状数组)
题意:给2个数字序列 a 和 b ,问按从小到达排序后,a中的哪些子串与b的名次匹配. a 的长度 N≤100,000,b的长度 M≤25,000,数字的大小 K≤25. 解法:[思考]1.X 暴力. ...
- 洛谷P3368 【模板】树状数组 2
P3368 [模板]树状数组 2 102通过 206提交 题目提供者HansBug 标签 难度普及/提高- 提交 讨论 题解 最新讨论 暂时没有讨论 题目描述 如题,已知一个数列,你需要进行下面两 ...
- P3368 【模板】树状数组 2(区间增减,单点查询)
P3368 [模板]树状数组 2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数数加上x 2.求出某一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表 ...
- 模板【洛谷P3368】 【模板】树状数组 2
P3368 [模板]树状数组 2 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数数加上x 2.求出某一个数的值 树状数组区间加,单点查询. code: #include <i ...
随机推荐
- dg环境连接ORA-00604,ORA-16000: database open for read-only access
报错信息 根据客户提供的报错信息, ORA-: error occurred at recursive SQL level ORA-: database open for read-only acce ...
- (六)在线文档编辑器的使用和数据字典(ueditor编辑器/my97datepicker日期控件)
使用ueditor编辑器注意: 1. 要把ueditor的jar包添加到WEB-INF/lib里. 2. 在做图片上传等功能时,必须重写struts的过滤器,否则图片流会被拦截程序无法得到图片. 3. ...
- MySQL INNER JOIN子句介绍
MySQL INNER JOIN子句介绍 MySQL INNER JOIN子句将一个表中的行与其他表中的行进行匹配,并允许从两个表中查询包含列的行记录. INNER JOIN子句是SELECT语句的可 ...
- 设计模式(三)——装饰器模式(Decorator Pattern)
发现太过于刻意按照计划来写博客,有点不实际,刚好最近在一个网课上复习AOP的知识,讲到了装饰器模式和代理模式,顺便复习总结一下. 首先了解一下装饰器模式,从名字里面可以看出来,装饰器模式就类似于房子装 ...
- C# 哥德巴赫猜想的实现方式 region分区编写
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threa ...
- HttpResponse与JasonResponse
两者的含义 我们都知道后台给前台返回的数据都是字符串类型,那么怎么返回成为一个问题 HttpResponse与JasonResponse都是django中后台给前台返回数据的方法, 并且他们最后走的都 ...
- 基2时抽8点FFT的matlab实现流程及FFT的内部机理
前言 本来想用verilog描述FFT算法,虽然是8点的FFT算法,但写出来的资源用量及时延也不比调用FFT IP的好, 还是老实调IP吧,了解内部机理即可,无需重复发明轮子. 参考 https:// ...
- JS实现数组去重(重复元素保留一个)
1.遍历数组法 它是最简单的数组去重方法(indexOf方法) 实现思路:新建一个数组,遍历去要重的数组,当值不在新数组的时候(indexOf为-1)就加入该新数组中: var arr=[2,8,5, ...
- 【2017-11-26】Linq表连接查询
class Program { static void Main(string[] args) { //Linq创建的数据库上下文对象db DataClasses2DataContext db = n ...
- Spring入门篇——AOP基本概念
1.什么是AOP及实现方式 什么是AOP AOP:Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术 主要 ...