线段树 POJ 3468 A Simple Problem with Integers

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 abc" means adding c to each of AaAa+1, ... , Ab. -10000 ≤ c ≤ 10000.

"Q ab" 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
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
long long a[100217*4];
long long col[100217*4];
int temp=1;
void build(int rt, int begin, int end)
{
    int m=(begin+end)/2;
    if(begin==end)
    {
        scanf("%I64d",&a[rt]);
        return ;
    }
    build( rt << 1, begin, m);
    build( 1 + (rt << 1), m + 1,end);
    a[rt] = a[rt << 1] + a[1 + (rt << 1)];
}
void update(int rt, int begin, int end, int x, int y, int v)
{
    int m=(begin+end)/2;
    if(x>end||y<begin)
        return ;
    if(end<=y&&begin>=x)
    {
        a[rt]+=(end-begin+1)*v;
        col[rt]+=v;
        //printf("%d %d %d %d %d\n",col[rt], begin, end, rt, a[rt]);
        return ;
    }
    if(col[rt]!=0)
    {
        a[rt<<1] += (m-begin+1)*col[rt];
        a[(rt<<1)+1] += (end-(m+1)+1)*col[rt];
        col[rt<<1] += col[rt] ;
        col[(rt<<1)+1] += col[rt] ;
        col[rt] = 0;
    }
    update( rt << 1, begin, m, x, y, v);
    update( 1 + (rt << 1), m + 1,end, x, y, v);
    a[rt] = a[rt << 1] + a[1 + (rt << 1)];
}
long long query(int rt, int begin, int end, int x, int y)
{

    int m=(begin+end)/2;
    if(x>end||y<begin)
        return 0;
    if(end<=y&&begin>=x)
    {
        //printf("%d-\n",rt);
        //printf("%d\n",a[rt]);
       long long t=a[rt];
        return t;
    }
    if(col[rt]!=0)
    {
        a[rt<<1 ]+= (m-begin+1)*col[rt];
        a[(rt<<1)+1] += (end-(m+1)+1)*col[rt];
        col[rt<<1] += col[rt] ;
        col[(rt<<1)+1] += col[rt] ;
        col[rt] = 0;
    }
    long long p1 = 0,p2 = 0;
    p1 = query( rt << 1, begin, m, x, y);
    p2 = query( 1 + (rt << 1), m + 1,end, x, y);
    //printf("%d %d\n",p1,p2);
    return p1+p2;
    //a[rt]=a[rt << 1] + a[1 + (rt << 1)];
}
int main()
{
    int T,n,m;
    while(scanf("%d%d",&n,&m)!=-1)
    {
        build(1,1,n);
       // puts("1");
        memset(col,0,sizeof(col));
       // getchar();
       // printf("%d\n",a[1]);
       while(m--)
       {
           //getchar();
           int x,y,v;
           char ch[10];
           scanf("%s",&ch);
           //printf("%c\n",ch);
           if(ch[0]=='Q')
           {
               scanf("%d%d", &x, &y);
               printf("%lld\n", query(1,1,n,x,y));
              // puts("y");
//               for(int i=1;i<n*4;i++)
//                    printf("%I64d %d\n",a[i],i);
           }
           else
           {
               //puts("x");
               scanf("%d%d%d", &x, &y, &v);
                update(1,1,n,x,y,v);
                //printf("%d\n",a[1]);
//                for(int i=1;i<n*4;i++)
//                    printf("%I64d %d\n",a[i],i);
           }
       }

    }
    return 0;
}

时间: 2024-10-26 21:38:51

线段树 POJ 3468 A Simple Problem with Integers的相关文章

POJ 3468 A Simple Problem with Integers(线段树)

题目链接:http://poj.org/problem?id=3468 A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 56005   Accepted: 16903 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with

poj 3468 A Simple Problem with Integers 【线段树-成段更新】

题目:poj 3468 A Simple Problem with Integers 题意:给出n个数,两种操作 1:l -- r 上的所有值加一个值val 2:求l---r 区间上的和 分析:线段树成段更新,成段求和 树中的每个点设两个变量sum 和 num ,分别保存区间 l--r 的和 和l---r 每个值要加的值 对于更新操作:对于要更新到的区间上面的区间,直接进行操作 加上 (r - l +1)* val .下面的区间标记num += val 对于求和操作,每次进行延迟更新,把num值

POJ 3468 A Simple Problem with Integers(线段树区间更新)

题目地址:POJ 3468 打了个篮球回来果然神经有点冲动..无脑的狂交了8次WA..居然是更新的时候把r-l写成了l-r... 这题就是区间更新裸题.区间更新就是加一个lazy标记,延迟标记,只有向下查询的时候才将lazy标记向下更新.其他的均按线段树的来就行. 代码如下: #include <iostream> #include <cstdio> #include <cstring> #include <math.h> #include <stac

poj 3468:A Simple Problem with Integers(线段树,区间修改求和)

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 58269   Accepted: 17753 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of

线段树(成段更新) POJ 3468 A Simple Problem with Integers

题目传送门 1 /* 2 线段树-成段更新:裸题,成段增减,区间求和 3 注意:开long long:) 4 */ 5 #include <cstdio> 6 #include <iostream> 7 #include <algorithm> 8 #include <cstring> 9 #include <cmath> 10 using namespace std; 11 12 #define lson l, mid, rt <<

poj 3468 A Simple Problem with Integers (线段树 成段更新 加值 求和)

题目链接 题意: 只有这两种操作 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. 分析:自己写的有点麻烦了,写的时候手残+脑残,改了好久. val+lazy*(r-l+1)表示和,如果lazy==0表示当前区间加的值不统一. 1 #include <iostream

POJ 3468 A Simple Problem with Integers(线段树 区间更新)

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. In

POJ 3468 A Simple Problem with Integers 【树状数组】

题目链接:http://poj.org/problem?id=3468 题目大意:给出一组数组v[i],有两种操作,一种给出两个数a,b,要求输出v[a]到v[b]之间的和,另一种给出三个数a,b,c,让v[a]到v[b]之间的数全都加上c. 完全是树状数组能够实现的功能,但是如果就这样单纯的套用模板,做第二种操作是更新每个值,这样的操作就有可能超时. 换一种思路,既然第二种操作是给某区间上的所有数加上相同的值,那么应该是能够简化的才对. 假设数组sum[i]为原数组从v[1]到v[i]的和,数

POJ 3468 A Simple Problem with Integers(详细题解)

这是个线段树题目,做之前必须要有些线段树基础才行不然你是很难理解的. 此题的难点就是在于你加的数要怎么加,加入你一直加到叶子节点的话,复杂度势必会很高的 具体思路 在增加时,如果要加的区间正好覆盖一个节点,则增加其节点的Inc值,不再往下走,否则要更新Sum(加上本次增量),再将增量往下传. 这样更新的复杂度就是O(log(n))在查询时,如果待查区间不是正好覆盖一个节点,就将节点的Inc往下带,然后将Inc代表的所有增量累加到Sum上后将Inc清0,接下来再往下查询. Inc往下带的过程也是区