poj 3468 A Simple Problem with Integers(线段树 [区间更新])

A Simple Problem with Integers
Time Limit: 5000MS Memory Limit: 131072K
Total Submissions: 78109 Accepted: 24051
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.

题意:

         给出了一个序列,你需要处理如下两种询问。

          "C a b c"表示给[a, b]区间中的值全部增加c (-10000 ≤ c ≤ 10000)。


           "Q a b" 询问[a, b]区间中所有值的和。

            第一行包含两个整数N, Q。1 ≤ N,Q ≤ 100000.

           第二行包含n个整数,表示初始的序列A (-1000000000 ≤ Ai ≤ 1000000000)。

             接下来Q行询问,格式如题目描述。

思路:

        一看本题就是区间更新,与单点更新有所不同

       有关update函数我们需要pushdown函数来维护整个区间的值,不是和单点更新相同,所以如下。

注意:

    本题大坑:

    我做的时候数组开小了,不仅sum要4倍的,而且add,num,均要四倍,一下午把我给郁闷了

维护函数:      

void pushup(int v)
{
   sum[v]=sum[v<<1]+sum[v<<1|1];
}

void pushdown(int l,int r,int v)
{
	if(add[v]!=0) 
	{   
        add[v<<1]+= add[v]; //左子树需要加
	add[v<<1|1]+=add[v]; //右子树需要加
		
        sum[v<<1]+= (mid+1-l)*add[v];//左子树求和 
        sum[v<<1|1]+=(r-mid)*add[v]; //右子树求和 
        add[v]=0;//这儿不能少  
       }  
}

void update(int l,int r,int v,int lpos,int rpos,int x)
{
	if(l>rpos||r<lpos)
	return ;
	if(l>=lpos&&r<=rpos)
	{
	  sum[v]+=(LL)(r-(l-1))*x;
	  add[v]+=x;
	  return ;
	}
	pushdown(l,r,v);
	if(l<=mid) 
	update(lson,lpos,rpos,x);
	if(r>mid)
	update(rson,lpos,rpos,x);
	pushup(v);
}

本人AC代码:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
#define  MAX 100000
typedef long long int LL;
#define mid (l+r>>1)
#define lson l,mid,v<<1
#define rson mid+1,r,v<<1|1
LL sum[4*MAX+20],num[4*MAX+5],add[4*MAX+5];//注意范围

void init()
{
	memset(sum,0,sizeof(sum));
	memset(add,0,sizeof(add));
	memset(num,0,sizeof(num));
}

void pushup(int v)
{
   sum[v]=sum[v<<1]+sum[v<<1|1];
}

void pushdown(int l,int r,int v)
{
	if(add[v]!=0) 
	{   
        add[v<<1]+= add[v]; 
	add[v<<1|1]+=add[v];  
		
        sum[v<<1]+= (mid+1-l)*add[v]; 
        sum[v<<1|1]+=(r-mid)*add[v];  
        add[v]=0;  
        }  
}

void build(int l,int r,int v)
{
  add[v]=0;
  if(l==r)
  {
  	sum[v]=num[l];
  	return ;
  }
  	build(lson);
  	build(rson);
    pushup(v);
}

void update(int l,int r,int v,int lpos,int rpos,int x)
{
	if(l>rpos||r<lpos)//这儿剪枝不能少
	return ;
	if(l>=lpos&&r<=rpos)
	{
	  sum[v]+=(LL)(r-(l-1))*x;//注意(LL)和(r-(l-1))
	  add[v]+=x;
	  return ;
	}
	pushdown(l,r,v);
	if(l<=mid) 
	update(lson,lpos,rpos,x);
	if(r>mid)
	update(rson,lpos,rpos,x);
	pushup(v);
}

LL query(int l,int r,int v,int lpos,int rpos)
{
	if(l>rpos||r<lpos)//同上
	return 0;
	if(l>=lpos&&r<=rpos)
    return sum[v];
    pushdown(l,r,v);
    return query(lson,lpos,rpos)+query(rson,lpos,rpos);
    
}

int main()
{
  int n,m;
  while(~scanf("%d%d",&n,&m))
   {	
	init();
	for(int i=1;i<=n;i++)
	   scanf("%lld",&num[i]);
 	build(1,n,1);
	while(m--)
	{
	  char opr;
	  getchar();//他少了会很难看的
	  scanf("%c",&opr); 
	  int a,b,c;
          if(opr=='Q')
	  {
	   scanf("%d%d",&a,&b);
	   LL ans=query(1,n,1,a,b);
	   printf("%lld\n",ans);
	 }
	 else
	 {
	 scanf("%d%d%d",&a,&b,&c);
	 update(1,n,1,a,b,c);
        }			
       }
   }
  return 0;
}


队友AC代码:

#include <stdio.h>
#define N 100100
#define LL long long
#define lson l,m,v<<1
#define rson m+1,r,v<<1|1
LL add[4*N];
LL sum[4*N];

void PushUP(int v)
{
    sum[v]=sum[v<<1]+sum[v<<1|1];
}

void PushDown(int v,int m)
{
    if(add[v])
    {
        add[v<<1]+=add[v];
        add[v<<1|1]+=add[v];
        sum[v<<1]+=(m-(m>>1))*add[v];
        sum[v<<1|1]+=(m>>1)*add[v];
        add[v]=0;
    }
}

void Build(int l,int r,int v)
{
    add[v]=0;
    if(l==r)
    {
        scanf("%lld",&sum[v]);
        return;
    }
    int m=(l+r)>>1;
    Build(lson);
    Build(rson);
    PushUP(v);
}

void Update(int L,int R,int c,int l,int r,int v)
{
    if(L<=l&&R>=r)
    {
        add[v]+=(LL)c;
        sum[v]+=(LL)c*(r-l+1);
        return;
    }
    PushDown(v,r-l+1);
    int m=(l+r)>>1;
    if(L<=m)
        Update(L,R,c,lson);
    if(R>m)
        Update(L,R,c,rson);
    PushUP(v);
}

LL Query(int L,int R,int l,int r,int v)
{
    if(L<=l&&R>=r)
        return sum[v];
    PushDown(v,r-l+1);
    int m=(l+r)>>1;
    LL ret=0;
    if(L<=m)   ret+=Query(L,R,lson);
    if(R>m)    ret+=Query(L,R,rson);
    return ret;
}

int main()
{
    int m,n;
    scanf("%d%d",&n,&m);
    Build(1,n,1);
    for(int i=0;i<m;i++)
    {
        char s[2];
        int a,b,c;
        scanf("%s",s);
        if(s[0]=='Q')
        {
            scanf("%d %d",&a,&b);
            printf("%lld\n",Query(a,b,1,n,1));
        }
        else
        {
            scanf("%d %d %d",&a,&b,&c);
            Update(a,b,c,1,n,1);
        }
    }
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值