【POJ-3468】A Simple Problem with Integers

74 阅读1分钟
题意

n个数,m次操作 Q x y是输出第x个数到第y个数的和 C x y z 是把第x个数到第y个数之间的每一个数都加z

 

样例
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

 



 

AC代码
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int MAXN = 9e5 + 111;   //如果是9e4 + 111,就算开的不够
long long sum1[MAXN];
long long sum2[MAXN];
long long a[MAXN];
int n,m;
int lowbit(int x)
{
    return x&(-x);
}

///效果:把x位置后面所有的数的值+w
void add(int x,long long w)
{
    for (int i=x;i<=n;i+=lowbit(i))
    {
        sum1[i]+=w;//维护前缀和c[i]
        sum2[i]+=w*(x-1);//维护前缀和c[i]*(n-1)
    }
}


///效果:把x位置到y位置所有的数的值+w
//原理:先把x后面的数都加上w,再把y后面的数都减去w。这样就达到了“x位置到y位置所有的数的值加w”的目的
void range_add(int x,int y,long long val)
{
    add(x,val);  //x后面的值加w
    add(y+1,-val);//y后面的值都减去w
}


///求1~x的和
long long sum(int x)
{
    long long ans=0;
    for (int i=x;i>0;i-=lowbit(i))
    {
        ans+=x*sum1[i]-sum2[i];

    }
    return ans;
}


///求x~y的和
//原理:[x,y]之间的和 = [1,y]之间的和 - [1,x]之间的和
long long range_sum(int x,int y)
{
    return sum(y)-sum(x-1);
}


int main()
{
    //freopen("a.txt","r",stdin);
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        add(i,a[i]-a[i-1]);//维护差分数组
    }

    for(int i=1;i<=m;i++)
    {
        char op;
        int x,y;
        long long z;
        cin>>op;
        if(op=='Q')
        {
            scanf("%d%d",&x,&y);
            cout<<range_sum(x,y)<<endl;
        }
        else if(op=='C')
        {
            scanf("%d %d %lld",&x,&y,&z);
            range_add(x,y,z);
        }
    }
  return 0;
}

 

题源:poj.org/problem?id=…
参考:www.cnblogs.com/bluefly-hrb…