POJ-3468-A Simple Problem with Integers(线段树 区间修改(区间加减) 区间查询)

POJ-3468-A Simple Problem with Integers(线段树 区间修改 区间查询)

A Simple Problem with Integers

Time Limit: 5000MS   Memory Limit: 131072K

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.

Source


单点修改的时间复杂度 n^2logn

lazy标记  时间复杂度  nlogn     少了对每个结点修改的时间

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
#define MAXN 100000
typedef struct segmentree
{
    int       left;
    int       right;
    long long maxn;
    long long sum;   //long long 型
    long long lazy;
}segmentree;
segmentree segtree[MAXN<<2];
long long a[MAXN];     //有long long型还是要同步long long 型,避免不必要的错误
void push_up(int root)
{
    segtree[root].sum = segtree[root<<1].sum + segtree[root<<1|1].sum;
}
void push_down(int root)
{
        if(segtree[root].lazy)
    {
        segtree[root<<1].sum += (segtree[root<<1].right - segtree[root<<1].left + 1)*segtree[root].lazy;
        segtree[root<<1|1].sum += (segtree[root<<1|1].right - segtree[root<<1|1].left + 1)*segtree[root].lazy;
        segtree[root<<1].maxn += segtree[root].lazy;
        segtree[root<<1|1].maxn += segtree[root].lazy;
        segtree[root<<1].lazy += segtree[root].lazy;
        segtree[root<<1|1].lazy += segtree[root].lazy;
        segtree[root].lazy = 0;                //下方lazy的同时就是在修改下面结点的数值,用lazy,可以在不用下面结点时,不对下面结点进行修改
    }
}
void CreateSegmentree(int root,int l,int r)  //创建线段树
{
    segtree[root].left = l;
    segtree[root].right = r;
    segtree[root].sum = 0;
    if(l == r)
    segtree[root].sum = a[l];
    else
    {
     int mid = (l+r)>>1;
     CreateSegmentree(root<<1,l,mid);
     CreateSegmentree(root<<1|1,mid+1,r);
     push_up(root);
     //递归的终止就是l==r
    }
    return;
}
long long query_sum(int root,int l,int r)      //查询线段树的各个区间。
{
    if(segtree[root].left == l && segtree[root].right == r)
    return segtree[root].sum;
    push_down(root);                        //相对于单点查询就多了一个push_down.进入子树就代表要下方lazy了
    int mid = (segtree[root].left + segtree[root].right) >> 1;
    if(r <= mid)
    return query_sum(root<<1, l, r);
    else if(l > mid)
    return query_sum(root<<1|1, l, r);
    else
    return query_sum(root<<1, l, mid) + query_sum(root<<1|1, mid+1, r);
}
void add(int root,int l,int r,int val)   //区间修改,三步操作,要l,r,
{
    if(segtree[root].left==l&&segtree[root].right==r)
    {
        segtree[root].sum += 1LL*(r-l+1)*val;   //因为sum是 long long 型的, 而val不是long long 型的 ,所以要有这种强制运算
        segtree[root].maxn += val;
        segtree[root].lazy  += val;


        return;
    }
    else
    {
        int mid= (segtree[root].left + segtree[root].right)>>1;
        push_down(root);
        if(r <= mid)
        add(root<<1, l, r, val);
        else if(l > mid)
        add(root<<1|1, l, r, val);
        else add(root<<1, l, mid, val),add(root<<1|1, mid+1, r, val);
        push_up(root);
    }
    return ;
}
int main()
{
    int n,m;
    int i;
    int l,r,val;
    char ops[20];
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
    }
    CreateSegmentree(1,1,n);
    while(m--)
    {
            scanf("%s",ops);
            if(ops[0]=='Q')
            {
                scanf("%d%d",&l,&r);
                printf("%lld\n",query_sum(1,l,r));
            }
            else
            {
                scanf("%d%d%d",&l,&r,&val);
                add(1,l,r,val);
            }
    }
  return 0;
}

猜你喜欢

转载自blog.csdn.net/xigongdali/article/details/80438627