Time Limit: 5000MS   Memory Limit: 131072K
Total Submissions: 97008   Accepted: 30285
Case Time Limit: 2000MS

Description

You have N integers, A1A2, ... , 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 A1A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.

Each of the next Q lines represents an operation.

"C a b c" means adding c to each of AaAa+1, ... , Ab. -10000 ≤ c ≤ 10000.

"Q a b" means querying the sum of AaAa+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.

Source

【题解】

线段树的区间递增。

输入数据的时候,要用到build过程,只有到达最底端的节点的时候,才输入这个节点。然后要记得往上更新它的父亲节点。即由sum[左儿子],sum[右儿子],更新sum[爸爸]。

然后是懒惰标记的使用<=修改。

我们到达的这个节点,如果它所代表的区间,被所询问的区间所覆盖。则直接修改这个节点的sum值即可,至于它的儿子们,则只要标记一下即可(add[rt] = xx),等我们需要访问它的时候再往下更新即可。

其他的则没有啥了。

【代码】

#include <cstdio>

int n, q;
__int64 sum[100001 * 4] = { 0 }, add[100001 * 4] = { 0 }; //开4倍是保险的做法。 void downpush(int rt, int len)//查看rt这个节点有没有懒惰标记。如果有的话就给它的儿子们贴上标记,同时清楚这个
{//标记,同时更新儿子的sum信息。
if (add[rt] != 0)
{
add[rt << 1] += add[rt];//左儿子加上父节点的懒惰标记值。
add[rt << 1 | 1] += add[rt];//右儿子也要加上父节点的懒惰标记值。
sum[rt << 1] += (len - (len >> 1))*add[rt];//左儿子的sum值要根据懒惰标记改变。不能写成(len - (len >> 1))*add[rt<<1],因为可能add[rt<<1]
//在未加上add[rt]之前已经不等于0了,而那个add[rt<<1]之前是已经累加过的,不能重复累加。
//这里的len-(len >> 1)则是这个区间它的长度。给每个位置都加上add[rt]。总和就是....
sum[rt << 1 | 1] += (len >> 1)*add[rt];//右儿子则是同理。
add[rt] = 0;//懒惰标记已经操作过了。就置为0;
}
} void uppush(int rt) //这是对儿子节点进行操作过后。回溯父节点的时候更新sum[rt];
{
sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
} void updata(int l, int r, int num, int begin, int end, int rt)//要求的区间是l,r,当前节点rt所代表的区间为begin,end;要增加的值为num;
{
if (l <= begin && end <= r) //如果当前这个节点所代表的区间被所要求的区间覆盖。那么就直接修改这个区间的和,然后加上懒惰标记
{//表示它的儿子节点们没有更新过。下次要记得更新。
add[rt] += num;
sum[rt] += (end - begin + 1)*num;//修改这个节点所代表的区间的区间和。
return;
}
downpush(rt, end - begin + 1);//看看这个节点有没有懒惰标记,如果有的话就先处理懒惰标记。
int m = (begin + end) >> 1;//获取中间节点。
if (l <= m)
updata(l, r, num, begin, m, rt << 1);//如果所要求的区间和当前这个节点所代表的区间的左半部分有交集,则递归往左递增。
//这样会不断地缩小区间。直到节点所代表的区间被那个交集覆盖(可能被分成了很多块)
if (m < r)//右边也是一样的,如果有小的区间有交集。则递归右边。
updata(l, r, num, m + 1, end, rt << 1 | 1);
uppush(rt);//这是用节点的儿子来更新节点的sum值。
} void build(int l, int r, int rt)//建树的过程<=>也即输入数据的过程(把数据输入到整棵树的最下面(叶子节点处)
{
if (l == r)
{
scanf("%I64d", &sum[rt]);//输入数据
return;
}
int mid = (l + r) >> 1;//获取中点
build(l, mid, rt << 1);//然后往左递归
build(mid + 1, r, rt << 1 | 1);//往右递归
uppush(rt);//然后根据儿子的sum信息来更新当前节点rt的sum信息。
} __int64 query(int l, int r, int begin, int end, int rt)//所询问的区间是l,r然后当前节点rt所代表的区间为begin,end;
{
if (l <= begin && end <= r)
{
return sum[rt];//如果当前节点所代表的区间被所询问的区间所覆盖,则直接返回这个区间的和。
}
downpush(rt, end - begin + 1);//如果这个节点有懒惰标记,则要往下更新儿子节点的sum值。
int mid = (begin + end) >> 1;//返回这个区间的中点
__int64 re = 0;
if (l <= mid)//如果这个节点所代表的区间的左半部分和所询问的区间有交集。则递归寻找那个交集。顺便把那个交集的和累加一下。
re += query(l, r, begin, mid, rt << 1);
if (mid < r)//这个是右边有交集的情况。也是一样累加右边的交集的区间和就可以了。
re += query(l, r, mid + 1, end, rt << 1 | 1);
return re;//返回总的区间和。
} int main()
{
//freopen("F:\\rush.txt", "r", stdin);
//freopen("F:\\rush_out.txt", "w", stdout);
scanf("%d%d", &n, &q);
build(1, n, 1); //输入n个数据
for (int i = 1; i <= q; i++)//输入q个操作。
{
char op[10];
scanf("%s", op);
int a, b, c;
if (op[0] == 'C')//如果是递增操作
{
scanf("%d%d%d", &a, &b, &c);
updata(a, b, c, 1, n, 1);//(a,b)的范围内都递增c。如果要递减,c就是负数,这点可以用在树状数组上面。
}
else
{
scanf("%d%d", &a, &b);//这是询问区间和。
printf("%I64d\n", query(a, b, 1, n, 1));
}
}
return 0;
}

【poj3468】A Simple Problem with Integers的更多相关文章

  1. 【poj3468】 A Simple Problem with Integers

    http://poj.org/problem?id=3468 (题目链接) 题意 给出一个序列,要求维护区间修改与区间求和操作. Solution 多年以前学习的树状数组区间修改又忘记了→_→. 其实 ...

  2. 【线段树成段更新成段查询模板】【POJ3468】A Simple Problem with Integerst

    题目大意: 2个操作 A.区间a b 增加 c B 查询a b; 注意事项:1.记住要清除标记 2.查询时要下放标记,但没必要向上更新 线段:自带的,不用建模 区间和性质:sum: /* WA 1次 ...

  3. 一本通1548【例 2】A Simple Problem with Integers

    1548:[例 2]A Simple Problem with Integers 题目描述 这是一道模板题. 给定数列 a[1],a[2],…,a[n],你需要依次进行 q 个操作,操作有两类: 1 ...

  4. POJ3468:A Simple Problem with Integers(线段树模板)

    A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 149972 ...

  5. 【POJ3468】【zkw线段树】A Simple Problem with Integers

    Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. On ...

  6. 【POJ3468】【树状数组区间修改】A Simple Problem with Integers

    Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. On ...

  7. 【POJ2761】【fhq treap】A Simple Problem with Integers

    Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. On ...

  8. 【成端更新线段树模板】POJ3468-A Simple Problem with Integers

    http://poj.org/problem?id=3468 _(:зゝ∠)_我又活着回来啦,前段时间太忙了写的题没时间扔上来,以后再说. [问题描述] 成段加某一个值,然后询问区间和. [思路] 讲 ...

  9. 【POJ 3468】 A Simple Problem with Integers

    [题目链接] 点击打开链接 [算法] 本题用线段树很容易写,但是,笔者为了练习树状数组,就用树状数组的方法做了一遍 我们不妨引入差分数组c, 则sum(n) = c[1] + (c[1] + c[2] ...

随机推荐

  1. Method of address space layout randomization for windows operating systems

    A system and method for address space layout randomization ("ASLR") for a Windows operatin ...

  2. ViewPager+Fragmrnt最简单结合方法

    Fragment和ViewPager 本博文系本菜鸟第一次博文展示,有错误之处请虽然提出 FragmentPagerAdapter 谷歌官方提供了这么一个adapter(FragmentPagerAd ...

  3. python 命令行參数解析

    本文是从我还有一个博客转载过来的,欢迎大家点击进去看一下,帮我添加点人气^_^ ImPyy 选择模块 依据python參考手冊的提示,optparse 已经废弃,应使用 argparse 教程 概念 ...

  4. win7桌面有个无法删除的IE图标

    平台:win7 症状:安装软件时没仔细看,结果装上了一大堆,挨个卸载后桌面残留了一个IE无法删除.在该图标上点右键只有“打开”“属性”“创建快捷方式”三个选项,主页默认为www.2345.com. 解 ...

  5. 学习笔记:Vue——自定义指令

    在Vue2.0中,代码复用和抽象的主要形式是组件.然鹅,有的情况下,你仍然需要对普通DOM元素进行底层操作,这时候就会用到自定义指令. 1.举个聚焦输入框的例子,全局注册focus指令 Vue.dir ...

  6. 洛谷——P1096 Hanoi双塔问题

    https://www.luogu.org/problem/show?pid=1096 题目描述 给定A.B.C三根足够长的细柱,在A柱上放有2n个中间有孔的圆盘,共有n个不同的尺寸,每个尺寸都有两个 ...

  7. Hadoop ecosystem 生态圈

    Cascading: hadoop上面的workflow Sqoop(发音:skup)是一款开源的工具,主要用于在Hadoop(Hive)与传统的数据库(mysql.postgresql...)间进行 ...

  8. 从反编译深入理解JAVA内部类类结构以及finalkeyword

    1.为什么成员内部类能够无条件訪问外部类的成员? 在此之前,我们已经讨论过了成员内部类能够无条件訪问外部类的成员,那详细到底是怎样实现的呢?以下通过反编译字节码文件看看到底.其实,编译器在进行编译的时 ...

  9. Java反射学习总结一(基础篇)

    Class类是Reflection API中核心的类,他位于Java.lang.Class 列出一些常用的方法. - getName() : 获得类的完整名字 - getFields() : 获得类的 ...

  10. swift学习第十五天:闭包

    闭包 闭包的介绍 闭包和OC中的block非常相似 OC中的block是匿名的函数 Swift中的闭包是一个特殊的函数 block和闭包都经常用于回调 注意:闭包和block一样,第一次使用时可能不习 ...