问题 A: 一个简单的整数问题

时间限制: 5 Sec  内存限制: 128 MB
提交: 75  解决: 25
[提交][状态][讨论版][
命题人:quanxing][Edit] [TestData]

题目链接:http://acm.ocrosoft.com/problem.php?cid=1690&pid=0

题目描述

你有N个整数,A1A2...AN 你需要处理两种操作。 一种操作是在给定间隔中为每个数字添加一些给定数字。 另一种是要求给定间隔中的数字总和。

输入

第一行包含两个数字NQ.1≤NQ≤100000
第二行包含N个数字,A1A2...AN的初始值。 -1000000000≤AI≤1000000000
接下来的Q行中的每一行代表一个操作。
“C a b c”表示将C添加到AaAa + 1...Ab中的每一个。 -10000≤c≤10000
“Q a b”表示查询AaAa + 1...Ab的总和。

输出

你需要回到Q个询问,每个询问一行。

样例输入

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

样例输出

4

55

9

15

思路:1e5的数据量,暴力区间更新查询肯定会TLE,用线段树可以快很多,此题是线段树的模板题。

代码:

#include<bits/stdc++.h>

using namespace std;

#pragma warning(disable:4996)

#define maxn 100005

#define ll long long

ll chushi[maxn], sum[maxn * 4], lazy[maxn * 4];//记得开4倍空间

void pushup(int rt)

{

    sum[rt] = sum[2 * rt] + sum[2 * rt + 1];

}

void pushdown(int rt, int len)

{

    if (lazy[rt])

    {

         lazy[2 * rt] += lazy[rt];

         lazy[2 * rt + 1] += lazy[rt];

         sum[2 * rt] += (len - len / 2)*lazy[rt];

         sum[2 * rt + 1] += (len / 2)*lazy[rt];

         lazy[rt] = 0;

    }

}

void build(int l, int r, int rt)

{

    lazy[rt] = 0;

    if (l == r)//叶节点赋值

    {

         sum[rt] = chushi[l];

         return;

    }

    int mid = (l + r) / 2;//递归建树——左子树,右子树

    build(l, mid, 2 * rt);

    build(mid + 1, r, 2 * rt + 1);

    pushup(rt);//更新父亲节点的值

}

ll qurry(int x, int y, int l, int r, int rt)

{

    //如果这个区间被完全包括在目标区间里面,直接返回这个区间的值

    if (x <= l && y >= r)

    {

         return sum[rt];

    }

    pushdown(rt, r - l + 1);

    int mid = (l + r) / 2;

    ll ans = 0;

    if (x <= mid)ans += qurry(x, y, l, mid, 2 * rt);//如果这个区间的左儿子和目标区间有交集那么搜索左儿子

    if (y > mid)ans += qurry(x, y, mid + 1, r, 2 * rt + 1);//如果这个区间的右儿子和目标区间有交集那么搜索右儿子

    return ans;

}

void update(int x, int y, int l, int r, int rt, int c)

{

    if (x <= l && y >= r)//区间更新,区间值加C,用到lazy数组去标记

    {

         lazy[rt] += c;

         sum[rt] += (r - l + 1)*c;

         return;

    }

    pushdown(rt, r - l + 1);

    int mid = (l + r) / 2;

    if (x <= mid)update(x, y, l, mid, 2 * rt, c);

    if (y > mid)update(x, y, mid + 1, r, 2 * rt + 1, c);

    pushup(rt);

}

int main()

{

    int n, q;

    cin >> n >> q;

    for (int i = 1; i <= n; i++)scanf("%lld", &chushi[i]);

    build(1, n, 1);

    while (q--)

    {

         char ch;

         scanf(" %c ", &ch);

         if (ch == 'Q')

         {

             ll a, b;

             scanf("%lld %lld", &a, &b);

             printf("%lld\n", qurry(a, b, 1, n, 1));



         }

         else

         {

             ll a, b, c;

             scanf("%lld %lld %lld", &a, &b, &c);

             update(a, b, 1, n, 1, c);

         }

    }

}