题目描述

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

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

Sample Output

4
55
9
15

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

解题思路

不同于改段求点或改点求段,这是一个改段求段的题目
有两种方法接题:
第一种为利用树状数组:

区间更新这里引进了一个数组delta数组,delta[i]表示区间 [i, n] 的共同增量,每次你需要更新的时候只需要更新delta数组就行了,因为每段区间更新的数都记录在这个数组
中,那怎么查询前缀和呐?
sum[i]=a[1]+a[2]+a[3]+......+a[i]+delta[1](i-0)+delta[2](i-1)+delta[3](i-2)+......+delta[i](i-i+1);
= sigma( a[x] ) + sigma( delta[x] * (i + 1 - x) )
= sigma( a[x] ) + (i + 1) * sigma( delta[x] ) - sigma( delta[x] * x )

(引用自吕程博客)
具体代码为

#include<iostream>
#include<string.h>
#include<stdio.h>
using namespace std;
const int M=100010;
long long add_sum[M];
long long add[M];
long long  ori[M];
int MN;
int Q;
int lowbit(int x)
{return x&(-x);
}
void update(int i,int v,long long* a)
{for(;i<=MN;i+=lowbit(i)){a[i]+=v;}
}
long long getsum(int r,long long  *a)
{long long resr=0;for(;r>0;r-=lowbit(r)){resr+=a[r];}return resr;
}
int main()
{//freopen("data.in","r",stdin);std::ios::sync_with_stdio(false);std::cin.tie(0);int tem;int l,r,val;while(cin>>MN>>Q){memset(ori,0,sizeof(ori));memset(add_sum,0,sizeof(add_sum));memset(add,0,sizeof(add));for(int i=1;i<=MN;i++){cin>>tem;update(i,tem,ori);}string ch;for(int i=0;i<Q;i++){cin>>ch;if(ch=="Q"){cin>>l>>r;cout<<getsum(r,ori)-getsum(l-1,ori)-l*getsum(l-1,add)+(r+1)*getsum(r,add)-getsum(r,add_sum)+getsum(l-1,add_sum)<<endl;}if(ch=="C"){cin>>l>>r>>val;update(l,val,add);update(r+1,-val,add);update(l,val*(l),add_sum);update(r+1,-val*(r+1),add_sum);}}}
}

注意:add_sum数组保存的是add[i]*i之后的值

第二种方法为利用线段树
可以写一个利用结构体实现的线段树,然后加懒标。我地AC代码是按照刘汝佳的板写的,我觉得他地方法比较简洁,更好玩
下面是代码(详解见算法竞赛入门经典-训练指南):

#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
const int M = 4*100010;
long long sumv[M];//线段树sum数组
long long add[M];
long long  x, y;//全局变量,update与query时使用
long long  addval;
long long  _sum;
//*********************//
void update(int id, int l, int r)
{long long m = l + (r - l) / 2;if (x <= l&&y >= r){add[id] += addval;}else{if (x <= m) update(2 * id, l, m);if (y>m) update(2 * id + 1, m+1, r);}sumv[id]=0;//!!!!!!!!!注意此步骤if (l<r){sumv[id] = sumv[2 * id] + sumv[2 * id + 1];}sumv[id] += add[id] * (r - l + 1);
}
void query(int id, int l, int r, long long addv)
{long long  m = l + (r - l) / 2;if (x <= l&&y >= r){_sum += sumv[id] + addv*(r - l + 1);}else{//addv += add[id];if (x <= m){query(2 * id, l, m, addv+add[id]);}if (y>m) query(2 * id + 1, m+1, r, addv+add[id]);}
}
int main()
{//freopen("data.in", "r", stdin);//freopen("data.out","w",stdout);std::ios::sync_with_stdio(false);std::cin.tie(0);long long  n, q;while (cin >> n >> q){memset(sumv, 0, sizeof(sumv));memset(add, 0, sizeof(add));for (int i = 1; i <= n; i++){cin >> addval;x = i;y = i;update(1, 1, n);}string ch;for (int i = 0; i<q; i++){cin >> ch;if (ch == "Q"){_sum = 0;cin >> x >> y;query(1, 1, n, 0);cout << _sum << endl;}if (ch == "C"){cin >> x >> y >> addval;update(1, 1, n);}}}
}

转载于:https://www.cnblogs.com/liuzhanshan/p/5894121.html

POJ3468--A Simple Problem with Integers--线段树/树状数组 改段求段相关推荐

  1. POJ3468 A Simple Problem with Integers【线段树 成段更新+求和 lazy标志】

    用longlong替换__int64也成. #define LL long long 输入输出用%lld Problem: 3468   User: qq1203456195 Memory: 4284 ...

  2. poj 3468 A Simple Problem with Integers(线段树区区)

    题目链接:  http://poj.org/problem?id=3468 题目大意:  给出N个数,和M次查询 C a b c  区间[a,b]的值都加上c Q a b     查询区间[a,b]值 ...

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

    题目链接 这个真费劲...其实我也不懂 为什么...大体思想是,如果把区间更新了,开始的时候只把用懒惰标记标记那个区间,而不更新底层元素,而如果查询的时候顺带着把lz标记给消除...多敲几遍,多调试一 ...

  4. poj3468 A Simple Problem with Integers

    http://acm.hust.edu.cn:8080/judge/problem/viewProblem.action?id=14607 题意:题目给你n个数,m个操作,接下来一行给你这n个数,接下 ...

  5. 【线段树】【模板】讲解 + 例题1 HDU - 1754 I Hate It (点修改分数)+ 例题二 POJ - 3468 A Simple Problem with Integers(区间加值)

    [线段树][模板]讲解 + 例题1 HDU - 1754 I Hate It (点修改分数)+ 例题二 POJ - 3468 A Simple Problem with Integers(区间加值) ...

  6. poj 3486 A Simple Problem with Integers(树状数组第三种模板改段求段)

    1 /* 2 树状数组第三种模板(改段求段)不解释! 不明白的点这里:here! 3 */ 4 #include<iostream> 5 #include<cstring> 6 ...

  7. poj 3243:A Simple Problem with Integers

    3243:A Simple Problem with Integers 查看 提交 统计 提示 提问 总时间限制:  5000ms  单个测试点时间限制:  2000ms  内存限制:  131072 ...

  8. CodeForces 390E Inna and Large Sweet Matrix(树状数组改段求段)

    CodeForces 390E Inna and Large Sweet Matrix(树状数组改段求段) 树状数组仅仅能实现线段树区间改动和区间查询的功能,能够取代不须要lazy tag的线段树.且 ...

  9. A Simple Problem with Integers POJ - 3468(线段树+区间查询+区间修改+建树+懒惰标记模板)+(树状数组)

    题意: 有一个数组,有两种操作.1: Q a b 求[a,b]的和 2:C a b c 给[a,b] 的所有元素都加上c. 题目: You have N integers, A1, A2, ... , ...

最新文章

  1. 数据库高可用性——SQL Server 2005数据库复制简单图解
  2. 2.6 更多导数例子-深度学习-Stanford吴恩达教授
  3. 除硬件外计算机系统不可缺少的是,除硬件外,计算机系统不可缺少的另外一部分是( )。...
  4. spring事务--使用aop事务代理对象调用方法示例
  5. java http请求 乱码_怎么解决java中的http请求乱码
  6. C语言程序程序设计—数组
  7. php写简单接口_使用PHP如何编写简单的App接口
  8. 【LeetCode-面试算法经典-Java实现】【054-Spiral Matrix(螺旋矩阵)】
  9. 【转】如何开始学习CoreCLR源代码?
  10. .Net的 Web项目的打包过程
  11. feignclient对象找不到_领导同事争相介绍对象,相亲N次,我找不到一条结婚的理由...
  12. 2012/7/9Intel面试题目
  13. PHP亿乐社区源码一比一高仿全开源源码
  14. CRCNN PCNN
  15. MATLAB中的转置 和 复数的共轭转置
  16. 电容中那些独有的特性和功能,你有了解吗?
  17. win10 启动后无法正常显示桌面/黑屏
  18. 使用github搭建网站
  19. vmware workstation 使用桥接网络 上网
  20. VS2017生成可执行程序,执行提示“不是有效的win32应用程序”

热门文章

  1. [学习笔记]电磁场与电磁波专业课程
  2. sdut 1028 Catch That Cow( BFS)
  3. 8.4 matlab用户界面设计工具
  4. Android NDK编程小试---实现java和c语言的互掉
  5. toeplitz--生成托普利兹矩阵
  6. 用GrabCut进行前景检测(对书中代码进行改进)Python
  7. Python爬取Json格式数据并读写(改中文编码)
  8. hourglass论文_DSSD(1)_论文_arxiv2017
  9. Netlink 介绍(译)
  10. 对未来无线解决方案的设想:家庭路由wifi充分利用方案