POJ3468(线段树+延迟更新)

A Simple Problem with Integers
Time Limit: 5000MS   Memory Limit: 131072K
Total Submissions: 43776   Accepted: 12806
Case Time Limit: 2000MS

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
 
//线段树的延迟更新,不然每次都操作到具体叶节点会耗费大量的时间!此题用add标记每个节点有无操作,不必每次都搜索至叶节点,从而节省大量的时间!
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
#define MAX 100003
typedef __int64 ll;
ll da[MAX],ans;
struct node 
{
 ll left,right,add;
 ll sum;
}tree[MAX*4];
//建立以left,right为左右边界,将数组a中元素存储在首地址从1开始的tree数组中
void build( ll id, ll left, ll right )
{
 tree[id].add=0;
    tree[id].left = left;
 tree[id].right = right;
    if( left == right )
    {
        tree[id].sum = da[left];
  return ;
    }
    else
    {
        ll mid = ( left + right )>>1;        
        build( id <<1, left, mid );
        build( id<<1|1, mid + 1, right );
        tree[id].sum = tree[id<<1].sum + tree[id<<1|1].sum;
 }
}
//修改
void updata( ll id, ll left, ll right, ll adi)
{
 if(tree[id].left==left&&tree[id].right==right)
 {
  tree[id].add+=adi;
  return ;
 }
 else 
 {
  if(tree[id].add!=0)
  {
   tree[id].sum+=(tree[id].right-tree[id].left+1)*tree[id].add;
   tree[id<<1].add+=tree[id].add;
   tree[id<<1|1].add+=tree[id].add;
   tree[id].add=0;
  }
  tree[id].sum+=( right-left+1)*adi;
  
  ll mid=(tree[id].left+tree[id].right)>>1;
  if(right<=mid)
   updata(id<<1,left,right,adi);
  else if(left>mid)
   updata(id<<1|1,left,right,adi);
  else
  {
   updata(id<<1,left,mid,adi);
   updata(id<<1|1,mid+1,right,adi);
  }
 }
}
//3.查询
//*****************************************************************
void query(ll id, ll left, ll right)
{
    if( tree[id].left==left&&tree[id].right== right)
    {
  if(tree[id].add==0)
  {
   ans+=tree[id].sum;
   return ;
  }
  else
  {
   ans+=tree[id].sum+(tree[id].right-tree[id].left+1)*tree[id].add;
   return ;
  }
    }
 else
 {
  if(tree[id].add!=0)
  {
   tree[id].sum+=(tree[id].right-tree[id].left+1)*tree[id].add;
   tree[id<<1].add+=tree[id].add;
   tree[(id<<1)+1].add+=tree[id].add;
   tree[id].add=0;
   
  }
  ll mid = (tree[id].left+tree[id].right)>>1;
  if(right<= mid )
   query( id <<1, left,right);
  else if(left>mid  )
   query( (id <<1)+ 1,left, right);
  else 
  {
   query( id <<1,  left,mid);
   query( (id<<1) + 1, mid+1,right );
  }
 }
}
int main()
{
 ll n,i,m;
 scanf("%I64d%I64d",&n,&m);
 //while(~scanf("%d%d",&n,&m))
// {
  for(i=1;i<=n;i++)
   scanf("%I64d",&da[i]);
  
  build(1,1,n);
  for(i=0;i<m;i++)
  {
   ll a,b,c;
   char op;
   scanf(" %c",&op);
   if(op=='C')
   {
    scanf("%I64d%I64d%I64d",&a,&b,&c);
    updata(1,a,b,c);
   }
   else if(op=='Q')
   {
    ans=0;
    scanf("%I64d%I64d",&a,&b);
    query(1, a,b);
    printf("%I64d\n",ans);
   }
  }
 //}
 return 0;
}
 

你可能感兴趣的:(数据结构,线段树,延迟更新)