A Simple Problem with Integers
Time Limit: 5000MS   Memory Limit: 131072K
Total Submissions: 97217   Accepted: 30358
Case Time Limit: 2000MS

Description

You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.

Input

The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.
The second line contains N numbers, the initial values of A1, A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.
Each of the next Q lines represents an operation.
"C a b c" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000.
"Q a b" means querying the sum of Aa, Aa+1, ... , Ab.

Output

You need to answer all Q commands in order. One answer in a line.

Sample Input

  1. 10 5
  2. 1 2 3 4 5 6 7 8 9 10
  3. Q 4 4
  4. Q 1 10
  5. Q 2 4
  6. C 3 6 3
  7. Q 2 4

Sample Output

  1. 4
  2. 55
  3. 9
  4. 15

Hint

The sums may exceed the range of 32-bit integers.

Source

 
这个题考察的是树状数组的区间更新而不是单点更新,单点更新会超时的;
树状数组天生用来动态维护数组前缀和,其特点是每次更新一个元素的值,查询只能查数组的前缀和,

但这个题目求的是某一区间的数组和,而且要支持批量更新某一区间内元素的值,怎么办呢?实际上,

还是可以把问题转化为求数组的前缀和。

首先,看更新操作update(s, t, d)把区间A[s]...A[t]都增加d,我们引入一个数组delta[i],表示

A[i]...A[n]的共同增量,n是数组的大小。那么update操作可以转化为:

1)令delta[s] = delta[s] + d,表示将A[s]...A[n]同时增加d,但这样A[t+1]...A[n]就多加了d,所以

2)再令delta[t+1] = delta[t+1] - d,表示将A[t+1]...A[n]同时减d

然后来看查询操作query(s, t),求A[s]...A[t]的区间和,转化为求前缀和,设sum[i] = A[1]+...+A[i],则

A[s]+...+A[t] = sum[t] - sum[s-1],

那么前缀和sum[x]又如何求呢?它由两部分组成,一是数组的原始和,二是该区间内的累计增量和, 把数组A的原始

值保存在数组org中,并且delta[i]对sum[x]的贡献值为delta[i]*(x+1-i),那么

sum[x] = org[1]+...+org[x] + delta[1]*x + delta[2]*(x-1) + delta[3]*(x-2)+...+delta[x]*1

= org[1]+...+org[x] + segma(delta[i]*(x+1-i))

= segma(org[i]) + (x+1)*segma(delta[i]) - segma(delta[i]*i),1 <= i <= x

这其实就是三个数组org[i], delta[i]和delta[i]*i的前缀和,org[i]的前缀和保持不变,事先就可以求出来,delta[i]和

delta[i]*i的前缀和是不断变化的,可以用两个树状数组来维护。

  1. #include<iostream>
  2. #include<stdio.h>
  3. #include<string.h>
  4. #define N 100010
  5. #define ll long long
  6. using namespace std;
  7. ll c1[N];//c1[i]表示i~n共同增加c1[i]
  8. ll c2[N];//c2[i]表示i~n一共增加c1[i]*i=c2[i]
  9. ll ans[N];//存放的前缀和
  10. ll n,m;
  11. string op;
  12. ll lowbit(ll x)
  13. {
  14. return x&(-x);
  15. }
  16. void update(ll x,ll val,ll *c)
  17. {
  18. while(x<=n)
  19. {
  20. c[x]+=val;
  21. x+=lowbit(x);
  22. }
  23. }
  24. ll getsum(ll x,ll *c)
  25. {
  26. ll s=;
  27. while(x>)
  28. {
  29. s+=c[x];
  30. x-=lowbit(x);
  31. }
  32. return s;
  33. }
  34. int main()
  35. {
  36. freopen("C:\\Users\\acer\\Desktop\\in.txt","r",stdin);
  37. while(scanf("%lld%lld",&n,&m)!=EOF)
  38. {
  39. memset(c1,,sizeof c1);
  40. memset(c2,,sizeof c2);
  41. memset(ans,,sizeof ans);
  42. for(int i=;i<=n;i++)
  43. {
  44. scanf("%lld",&ans[i]);
  45. ans[i]+=ans[i-];
  46. }
  47. getchar();
  48. for(int i=;i<=m;i++)
  49. {
  50. cin>>op;
  51. if(op=="C")
  52. {
  53. ll s1,s2,s3;
  54. scanf("%lld%lld%lld",&s1,&s2,&s3);
  55. update(s1,s3,c1);//c1~n共同增加了s3
  56. update(s2+,-s3,c1);//上一步操作使得s2~n多增加了s3所以这一步要减去
  57. update(s1,s1*s3,c2);
  58. update(s2+,-(s2+)*s3,c2);
  59. }
  60. else if(op=="Q")
  61. {
  62. ll s1,s2;
  63. scanf("%lld%lld",&s1,&s2);
  64. ll cur=ans[s2]-ans[s1-];//首先等于s1~s2这个区间的基础值
  65. cur+=getsum(s2,c1)*(s2+)-getsum(s2,c2);//0~s2对前缀和的影响
  66. cur-=getsum(s1-,c1)*(s1)-getsum(s1-,c2);//0~s1对前缀和的影响
  67. printf("%lld\n",cur);
  68. }
  69. }
  70. // for(int i=1;i<=n;i++)
  71. // cout<<getsum(i)<<" ";
  72. // cout<<endl;
  73. }
  74. }

POJ 3468 A Simple Problem with Integers(树状数组区间更新)的更多相关文章

  1. POJ3468 A Simple Problem With Integers 树状数组 区间更新区间询问

    今天学了很多关于树状数组的技巧.一个是利用树状数组可以简单的实现段更新,点询问(二维的段更新点询问也可以),每次修改只需要修改2个角或者4个角就可以了,另外一个技巧就是这题,原本用线段树做,现在可以用 ...

  2. HDU 4267 A Simple Problem with Integers --树状数组

    题意:给一个序列,操作1:给区间[a,b]中(i-a)%k==0的位置 i 的值都加上val  操作2:查询 i 位置的值 解法:树状数组记录更新值. 由 (i-a)%k == 0 得知 i%k == ...

  3. A Simple Problem with Integers(树状数组HDU4267)

    A Simple Problem with Integers Time Limit: 5000/1500 MS (Java/Others) Memory Limit: 32768/32768 K (J ...

  4. POJ.3468 A Simple Problem with Integers(线段树 区间更新 区间查询)

    POJ.3468 A Simple Problem with Integers(线段树 区间更新 区间查询) 题意分析 注意一下懒惰标记,数据部分和更新时的数字都要是long long ,别的没什么大 ...

  5. poj 3468 A Simple Problem with Integers 【线段树-成段更新】

    题目:id=3468" target="_blank">poj 3468 A Simple Problem with Integers 题意:给出n个数.两种操作 ...

  6. 线段树(成段更新) POJ 3468 A Simple Problem with Integers

    题目传送门 /* 线段树-成段更新:裸题,成段增减,区间求和 注意:开long long:) */ #include <cstdio> #include <iostream> ...

  7. poj 3468 A Simple Problem with Integers(线段树+区间更新+区间求和)

    题目链接:id=3468http://">http://poj.org/problem? id=3468 A Simple Problem with Integers Time Lim ...

  8. POJ 3468 A Simple Problem with Integers(线段树功能:区间加减区间求和)

    题目链接:http://poj.org/problem?id=3468 A Simple Problem with Integers Time Limit: 5000MS   Memory Limit ...

  9. POJ 3468 A Simple Problem with Integers(分块入门)

    题目链接:http://poj.org/problem?id=3468 A Simple Problem with Integers Time Limit: 5000MS   Memory Limit ...

  10. 【poj2155】Matrix(二维树状数组区间更新+单点查询)

    Description Given an N*N matrix A, whose elements are either 0 or 1. A[i, j] means the number in the ...

随机推荐

  1. StringBuffer的替换和反转和截取功能

    A:StringBuffer的替换功能 * public StringBuffer replace(int start,int end,String str): * 从start开始到end用str替 ...

  2. Python 接口测试(二)

    三:http状态码含义(来源于w3school): 状态码: 1xx: 信息 消息:          描述: 100 Continue   服务器仅接收到部分请求,但是一旦服务器并没有拒绝该请求,客 ...

  3. 深入浅出AQS之独占锁模式

    每一个Java工程师应该都或多或少了解过AQS,我自己也是前前后后,反反复复研究了很久,看了忘,忘了再看,每次都有不一样的体会.这次趁着写博客,打算重新拿出来系统的研究下它的源码,总结成文章,便于以后 ...

  4. iOS连续dismiss几个ViewController的方法

    原文链接:http://blog.csdn.net/longshihua/article/details/51282388 presentViewController是经常会用到的展现ViewCont ...

  5. 闲聊DOS命令

    使用DOS命令进入指定文件夹打开文本文件: 回车确定 先进入F盘: 回车后输入:  F: 然后回车就进入了F盘,如下图: 然后比如我们要打开 F:\电脑桌面文件\hosts文件.txt文件,打开步骤如 ...

  6. JavaWeb学习笔记——jquery中的dom操作

     jquery中的dom操作 废话不说:直接上例子: 1.添加节点-html页面 Append:向每个匹配的元素内部追加内容. <body> <ul id="city& ...

  7. C#对图片进行马赛克处理,可控制模糊程度

    using System.Drawing; using System.Drawing.Imaging; using System.Web.Mvc; namespace MVC2017_Sample.C ...

  8. Linux基础命令讲解(一)

    Linux命令基本格式: 命令 [参数] [路径文件] 方括号内容可省略 查看命令帮助手段: 1 man 命令名(man 还可以获取配置文件,函数的帮助) 2 命令 --help 3 help 命令( ...

  9. 初识Hibernate之继承映射

         前面的两篇文章中,我们介绍了两张表之间的各种相互关联映射关系,但往往我们也会遇到两张表甚至多张表之间共有着多个相同的字段.例如: 如图,student表和teacher表共同具有id,nam ...

  10. 设计模式之visitor模式,人人能懂的有趣实例

    设计模式,现在在网上随便搜都一大堆,为什么我还要写"设计模式"的章节呢? 两个原因: 1.本人觉得这是一个有趣的设计模式使用实例,所以记下来: 2.看着设计模式很牛逼,却不知道怎么 ...