poj3468 A Simple Problem with Integers

给定长度为N的数列A,然后输入M行操作指令。

第一类指令形如“C l r d”,表示把数列中第l~r个数都加d。

第二类指令形如“Q X”,表示询问数列中第x个数的值。

对于每个询问,输出一个整数表示答案。

输入格式

第一行包含两个整数N和M。

第二行包含N个整数A[i]。

接下来M行表示M条指令,每条指令的格式如题目描述所示。

输出格式

对于每个询问,输出一个整数表示答案。

每个答案占一行。

数据范围

1N,M1051≤N,M≤105,
|d|10000|d|≤10000,
|A[i]|1000000000|A[i]|≤1000000000

输入样例:

10 5
1 2 3 4 5 6 7 8 9 10
Q 4
Q 1
Q 2
C 1 6 3
Q 2

输出样例:

4
1
2
5


这次用线段树来实现,这里不带lazy标记的话时间复杂度降为O(n)
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ULL;
typedef long long ll;
#define form(i,n) for(int i=1;i<=n;i++)
#define forn(i,n) for(int i=0;i<n;i++)
#define mst(a) memset(a,0,sizeof(a))
#define P pair<int,int>
#define wh(T) while(T--)
const int MAX_N=1e7+10;
const int N=1e5+90;
const int inf=1e8;
const int SIZE=100010;
struct SegmentTree{
    int l,r;
    long long sum,add;
#define l(x) tree[x].l
#define r(x) tree[x].r
#define sum(x) tree[x].sum
#define add(x) tree[x].add
}tree[N*4];
int a[N],n,m;
void build(int p,int l,int r)//No.p, [l,r]
{
    l(p)=l,r(p)=r;
    if(l==r) { sum(p)=a[l]; return; }
    int mid=(l+r)/2;
    build(p*2,l,mid);
    build(p*2+1,mid+1,r);
    sum(p)=sum(p*2)+sum(p*2+1);
}

void spread(int p)
{
    if(add(p))
    {
        sum(p*2)+=add(p)*(r(p*2)-l(p*2)+1);
        sum(p*2+1)+=add(p)*(r(p*2+1)-l(p*2+1)+1);
        add(p*2)+=add(p);
        add(p*2+1)+=add(p);
        add(p)=0;
    }
}

void change(int p,int l,int r,int z)
{
    if(l<=l(p)&&r>=r(p))
    {
        sum(p)+=(long long)z*(r(p)-l(p)+1);
        add(p)+=z;
        return;
    }
    spread(p);
    int mid=(l(p)+r(p))/2;
    if(l<=mid) change(p*2,l,r,z);
    if(r>mid) change(p*2+1,l,r,z);
    sum(p)=sum(p*2)+sum(p*2+1);
}

long long ask(int p,int l,int r)
{
    if(l<=l(p)&&r>=r(p)) return sum(p);
    spread(p);
    int mid=(l(p)+r(p))/2;
    long long ans=0;
    if(l<=mid) ans+=ask(p*2,l,r);
    if(r>mid) ans+=ask(p*2+1,l,r);
    return ans;
}

int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    build(1,1,n);
    while(m--)
    {
        char op[2]; int x,y,z;
        scanf("%s%d%d",op,&x,&y);
        if(op[0]=='C')
        {
            scanf("%d",&z);
            change(1,x,y,z);
        }
        else printf("%I64d\n",ask(1,x,y));
    }
}