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相关推荐

  1. UESTC 1601 艾尔大停电2 二维树状数组+区间更新

    艾尔大停电2 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit  S ...

  2. hdu3966 树链剖分点权模板+线段树区间更新/树状数组区间更新单点查询

    点权树的模板题,另外发现树状数组也是可以区间更新的.. 注意在对链进行操作时方向不要搞错 线段树版本 #include<bits/stdc++.h> using namespace std ...

  3. HDU 4031 Attack(线段树/树状数组区间更新单点查询+暴力)

    Attack Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others) Total Sub ...

  4. hdu 1556:Color the ball(第二类树状数组 —— 区间更新,点求和)

    Color the ball Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

  5. 树状数组区间修改和区间求和

    最一般树状数组能做到的操作是单点修改,区间求和,都是log(n)级别的.原理就是用树状数组维护a[i]的部分和. 想要做到修改区间,求单点值也很简单,用树状数组维护a[i]的差分数组d[i]的部分和既 ...

  6. 校门外的树——树状数组+区间修改

    校门外的树 [题目分析]题目描述的是一种区间修改,看起来好像要用线段树.但是对于这种区间内部没有差别并且查询的是区间内的类别的问题,是可以转化为树状数组进行的.毕竟树状数组更加简单. 我们的关注点应该 ...

  7. Color the ball(树状数组区间更新+单点求值)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1556 Color the ball Time Limit: 9000/3000 MS (Java/Ot ...

  8. 树状数组 区间加 区间求和_EXCEL统计区间个数的专属函数

    这次我们学习一个新的函数! 数字区间个数统计 如下图,要求统计四个成绩区间段的人数. 如果只统计一个区间内的人数,比如上图统计60-80分之间的人数,你会怎么办呢? 1.条件计数 =COUNTIF(B ...

  9. HRBUST 1161 树状数组区间更新求和

    Leyni Time Limit: 3000 MS Memory Limit: 65536 K Total Submit: 267(64 users) Total Accepted: 82(57 us ...

最新文章

  1. 从view 得到图片
  2. 蓝牙4.0技术分析1-广播者角色
  3. HDU - 7009 树上游走(树的直径+容斥)
  4. Angular html property的值如何被更新的
  5. CWnd与HWND的区别与转换
  6. 关于proxy模式下,@Transactional标签在创建代理对象时的应用
  7. matlab 指定区域随机游走_了解随机游走模型和移动平均过程(Python)
  8. Vue.js(2.x)之插值
  9. ASP.NET MVC . Controller
  10. 使用matlab生成含正弦波表数据ROM
  11. 从设计心理学理解交互设计的原则
  12. 微信第三方登陆,无需注册一键登录,获取用户信息,PHP实现方法.
  13. CBR,VBR,ABR介绍
  14. P1336 课题选择
  15. 搜索习题-传教士与野人问题
  16. mysql中怎么防止数据丢失
  17. python 协程是啥_Python中的协程是什么
  18. Java小知识:多张图片合并成一张
  19. 代码式动态录入生成个人简历页面html页面前端源码
  20. android7.0/8.0使用第三方软件battery monitor等软件读取电池电量,显示电池容量与实际容量不符修改

热门文章

  1. Deep Learning(深度学习)学习笔记整理系列之(五)
  2. asterisk源码目录结构
  3. 迁移物理solaris系统至一个区域
  4. 审核网络安全的十大必备工具
  5. MySQL性能测试工具sysbench的安装和使用
  6. node 之 redis 使用
  7. 前端开发应届生面试指南(含各大公司具体指南及面试真题)
  8. 设计模式-组合+策略模式
  9. Android应用程序窗口(Activity)的测量(Measure)、布局(Layout)和绘制(Draw)过程分析(上)...
  10. helloworld 1 2結合版 (有意思)