ACM: 线段树 poj 3468

来源:互联网 发布:java回退流 编辑:程序博客网 时间:2024/05/17 01:47
ASimple Problem with Integers
Description

You have N integers, A1,A2, ... , AN. You need to dealwith two kinds of operations. One type of operation is to add somegiven number to each number in a given interval. The other is toask 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 ofA1, A2, ... ,AN. -1000000000 ≤ Ai ≤1000000000.
Each of the next Q lines represents an operation.
"C a b c" means adding c to each ofAa, Aa+1, ... ,Ab. -10000 ≤ c ≤ 10000.
"Q a b" means querying the sum ofAa, Aa+1, ... ,Ab.

Output

You need to answer all Q commands in order. One answer ina 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 exceedthe range of 32-bit integers.
 
题意: 一组数组, 对它有两种操作, QA 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(intl, 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, intr, 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, intr, 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;
}
0 0
原创粉丝点击