您的位置:首页 > 其它

ACM: 线段树 poj 3468

2016-05-19 23:24 447 查看
A
Simple Problem with Integers
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

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.

 
题意: 一组数组, 对它有两种操作, Q
A B: 访问区间[A,B]的数组累加和, C A B C: 区间[A,B]内每个

      元素都加上C.

 
解题思路:

    1.
经典的线段树题目, 只需在线段树每个节点上设置sum和add: 累加和,增量域. 题目迎刃而解.

    2.
操作C时, 当满足当前区间[A,B]时, p->add =
p->add + C; 修改区间的增量即可.

                 当不满足时,
继续往左右区间改变增量之前要将当前的区间增量加入sum,

                            
p->sum = p->sum +
(p->r - p->l + 1) *
p->add;

       操作Q时,当满足当前区间[A,B]时,
记录结果result = p->sum +
(p->r - p->l +
1)*p->add;

               当不满足时,
继续往左右区间查找之前要将当前的增量分配到左右子树区间上,

               p->left->add
+= p->add;
p->right->add +=
p->add; p->add = 0; //最后记得清除.

              
p->sum += (p->r - p->l
+ 1)*p->add;

    
3. 最后, 要注意累加的结果会超出32位整型, 并且传入C增量时要用整型64位.

 
代码:
#include
<cstdio>

#include <iostream>

#include <cstring>

using namespace std;

#define MAX 100005
struct node

{

 int l, r;

 __int64 sum, add; //sum:区间和, add:区间的增量

}pt[MAX*4];
int n, m;

__int64 g[MAX];

__int64 a, b, c;

char ch[2];

__int64 result;
void buildTree(int
l, int r, int pos)

{

 pt[pos].l = l, pt[pos].r = r;

 pt[pos].add = 0;

 if(l == r)

 {

  pt[pos].sum = g[l];

  return ;

 }

 int mid = (pt[pos].l+pt[pos].r)/2;

 buildTree(l, mid, pos*2);

 buildTree(mid+1, r, pos*2+1);

 pt[pos].sum =
pt[pos*2].sum+pt[pos*2+1].sum;

}
void add(int l, int
r, int pos, __int64 c)

{

 if(pt[pos].l == l
&& pt[pos].r == r)

 {

  pt[pos].add += c;

  return ;

 }

 int mid = (pt[pos].l+pt[pos].r)/2;

 pt[pos].sum += (r-l+1)*c;

 if(r <= mid)

  add(l, r, pos*2, c);

 else if(l > mid)

  add(l, r, pos*2+1, c);

 else

 {

  add(l, mid, pos*2, c);

  add(mid+1, r, pos*2+1,
c);

 }

}
void find(int l, int
r, int pos)

{

 if(pt[pos].l == l
&& pt[pos].r == r)

 {

  result += (pt[pos].sum +
(r-l+1)*pt[pos].add);

  return ;

 }

 int mid = (pt[pos].l+pt[pos].r)/2;

 pt[pos].sum +=
(pt[pos].r-pt[pos].l+1)*pt[pos].add;

 pt[pos*2].add += pt[pos].add;

 pt[pos*2+1].add += pt[pos].add;

 pt[pos].add = 0;

 if(r <= mid)

  find(l, r, pos*2);

 else if(l > mid)

  find(l, r, pos*2+1);

 else

 {

  find(l, mid, pos*2);

  find(mid+1, r, pos*2+1);

 }

}
int main()

{

 int i;

// freopen("input.txt","r",stdin);

 while(scanf("%d %d",&n,
&m) != EOF)

 {

  for(i = 1; i <=
n; ++i)

   scanf("%I64d",&g[i]);

  buildTree(1, n, 1);

  for(i = 1; i <=
m; ++i)

  {

   scanf("%s",ch);

   if(ch[0] ==
'C')

   {

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

    add(a,
b, 1, c);

   }

   else if(ch[0]
== 'Q')

   {

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

    result
= 0;

    find(a,
b, 1);

    printf("%I64d\n",result);

   }

  }

 }

 return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: