树状数组 区间update/query
Re
【问题引入】
对于区间修改、区间查询这样的简单问题,打一大堆线段树确实是不划算,今天来介绍一下区间查询+区间修改的树状数组
【一些基础】
树状数组的基本知识不再介绍,请自行百度
我们假设sigma(r,i)表示r数组的前i项和,调用一次的复杂度是log2(i)
设原数组是a[n],差分数组c[n],c[i]=a[i]-a[i-1],那么明显地a[i]=sigma(c,i),如果想要修改a[i]到a[j](比如+v),只需令c[i]+=v,c[j+1]-=v
【今天的主要内容】
我们可以实现NlogN时间的“单点修改,区间查询”,“区间修改,单点查询”,其实后者就是前者的一个变形,要明白树状数组的本质就是“单点修改,区间查询”
怎么实现“区间修改,区间查询”呢?
观察式子:
a[1]+a[2]+...+a[n]
= (c[1]) + (c[1]+c[2]) + ... + (c[1]+c[2]+...+c[n])
= n*c[1] + (n-1)*c[2] +... +c[n]
= n * (c[1]+c[2]+...+c[n]) - (0*c[1]+1*c[2]+...+(n-1)*c[n]) (式子①)
那么我们就维护一个数组c2[n],其中c2[i] = (i-1)*c[i]
每当修改c的时候,就同步修改一下c2,这样复杂度就不会改变
那么
式子①
=n*sigma(c,n) - sigma(c2,n)
于是我们做到了在O(logN)的时间内完成一次区间和查询
一件很好的事情就是树状数组的常数比其他NlogN的数据结构小得多,实际上它的计算次数比NlogN要小很多,再加上它代码短,是OI中的利器
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #define N 200100*8 6 using namespace std; 7 typedef long long ll; 8 int n,m; 9 ll a[N],c1[N],c2[N]; 10 struct io{ 11 char op[1<<26],*s; 12 io() 13 { 14 fread(s=op,1,1<<26,stdin); 15 } 16 inline int read() 17 { 18 register int u=0; 19 while(*s<48)s++; 20 while(*s>32)u=u*10+*s++-48; 21 return u; 22 } 23 }ip; 24 #define read ip.read 25 inline int lowbit(int x){return x&(-x);} 26 void add(ll *r,int pos, ll v) 27 { 28 for(;pos<=n;pos+=lowbit(pos))r[pos]+=v; 29 } 30 ll getsum(ll *r,int pos) 31 { 32 ll re=0; 33 for(;pos>0;pos-=lowbit(pos))re+=r[pos]; 34 return re; 35 } 36 ll sigma(int r) 37 { 38 ll sum1=r*getsum(c1,r),sum2=getsum(c2,r); 39 return sum1-sum2; 40 } 41 ll query(int x,int y) 42 { 43 return sigma(y)-sigma(x-1); 44 } 45 int flag,x,y;ll k; 46 int main() 47 { 48 n=read(); 49 for(int i=1;i<=n;i++) 50 { 51 a[i]=read(); 52 add(c1,i,a[i]-a[i-1]); 53 add(c2,i,(i-1)*(a[i]-a[i-1])); 54 }m=read(); 55 for(int i=1;i<=m;i++) 56 { 57 flag=read(); 58 if(flag==1) 59 { 60 x=read();y=read();k=read(); 61 add(c1,x,k);add(c1,y+1,-k); 62 add(c2,x,(x-1)*k);add(c2,y+1,y*(-k)); 63 } 64 else 65 { 66 x=read();y=read(); 67 printf("%lld\n",query(x,y)); 68 } 69 } 70 return 0; 71 }
View Code
230ms全场最快qaq
转载于:https://www.cnblogs.com/mczhuang/p/7662968.html
树状数组 区间update/query相关推荐
- UESTC 1601 艾尔大停电2 二维树状数组+区间更新
艾尔大停电2 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Submit S ...
- hdu3966 树链剖分点权模板+线段树区间更新/树状数组区间更新单点查询
点权树的模板题,另外发现树状数组也是可以区间更新的.. 注意在对链进行操作时方向不要搞错 线段树版本 #include<bits/stdc++.h> using namespace std ...
- HDU 4031 Attack(线段树/树状数组区间更新单点查询+暴力)
Attack Time Limit: 5000/3000 MS (Java/Others) Memory Limit: 65768/65768 K (Java/Others) Total Sub ...
- hdu 1556:Color the ball(第二类树状数组 —— 区间更新,点求和)
Color the ball Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) T ...
- 树状数组区间修改和区间求和
最一般树状数组能做到的操作是单点修改,区间求和,都是log(n)级别的.原理就是用树状数组维护a[i]的部分和. 想要做到修改区间,求单点值也很简单,用树状数组维护a[i]的差分数组d[i]的部分和既 ...
- 校门外的树——树状数组+区间修改
校门外的树 [题目分析]题目描述的是一种区间修改,看起来好像要用线段树.但是对于这种区间内部没有差别并且查询的是区间内的类别的问题,是可以转化为树状数组进行的.毕竟树状数组更加简单. 我们的关注点应该 ...
- Color the ball(树状数组区间更新+单点求值)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1556 Color the ball Time Limit: 9000/3000 MS (Java/Ot ...
- 树状数组 区间加 区间求和_EXCEL统计区间个数的专属函数
这次我们学习一个新的函数! 数字区间个数统计 如下图,要求统计四个成绩区间段的人数. 如果只统计一个区间内的人数,比如上图统计60-80分之间的人数,你会怎么办呢? 1.条件计数 =COUNTIF(B ...
- HRBUST 1161 树状数组区间更新求和
Leyni Time Limit: 3000 MS Memory Limit: 65536 K Total Submit: 267(64 users) Total Accepted: 82(57 us ...
最新文章
- 从view 得到图片
- 蓝牙4.0技术分析1-广播者角色
- HDU - 7009 树上游走(树的直径+容斥)
- Angular html property的值如何被更新的
- CWnd与HWND的区别与转换
- 关于proxy模式下,@Transactional标签在创建代理对象时的应用
- matlab 指定区域随机游走_了解随机游走模型和移动平均过程(Python)
- Vue.js(2.x)之插值
- ASP.NET MVC . Controller
- 使用matlab生成含正弦波表数据ROM
- 从设计心理学理解交互设计的原则
- 微信第三方登陆,无需注册一键登录,获取用户信息,PHP实现方法.
- CBR,VBR,ABR介绍
- P1336 课题选择
- 搜索习题-传教士与野人问题
- mysql中怎么防止数据丢失
- python 协程是啥_Python中的协程是什么
- Java小知识:多张图片合并成一张
- 代码式动态录入生成个人简历页面html页面前端源码
- android7.0/8.0使用第三方软件battery monitor等软件读取电池电量,显示电池容量与实际容量不符修改