文章标题 POJ 3468 : A Simple Problem with Integers (线段树)

来源:互联网 发布:c语言成绩查询系统湖北 编辑:程序博客网 时间:2024/06/06 19:13

A Simple Problem with Integers

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.

Input
The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.
The second line contains N numbers, the initial values of A1, A2, … , AN. -1000000000 ≤ Ai ≤ 1000000000.
Each of the next Q lines represents an operation.
“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.

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.

题意:有一个n个数的序列,然后有q个查询,每次查询有两种可能,第一中就是将区间【l,r】全部加上val,第二种就是将区间【l,r】所有的和sum。
分析:线段树区间求和,用sum来保存节点做在区间的和,然后用一个lazy标记setv数组,当需要向下更新再想下更新,不然lazy标记就是保存最新的值。
代码:

#include<iostream>#include<string>#include<cstdio>#include<cstring>#include<vector>#include<math.h>#include<map>#include<queue> #include<algorithm>using namespace std;const int inf = 0x3f3f3f3f;typedef pair<int,int> pii;const int maxn=100005<<2;int n,q;long long sum[maxn];//节点的sum值 long long val[maxn]; long long setv[maxn];//lazy标记 void push_up(int rt){//向上更新     sum[rt]=sum[rt*2]+sum[rt*2+1];}void push_down(int rt,int len){    if (setv[rt]){//有lazy标记就向左右孩子传递,自己改为0         setv[rt*2]+=setv[rt];        setv[rt*2+1]+=setv[rt];        sum[rt*2]+=(len-len/2)*setv[rt];        sum[rt*2+1]+=(len/2)*setv[rt];        setv[rt]=0;    }} void build(int rt,int l,int r){//建树     setv[rt]=0;    if (l==r){        scanf ("%lld",&sum[rt]);        return ;    }    int m=(l+r)>>1;    build(rt*2,l,m);    build(rt*2+1,m+1,r);    push_up(rt);}long long query(int rt,int l,int r,int ql,int qr){    if (ql<=l&&r<=qr){//如果当前的区间在需要的查询的区间内直接返回         return sum[rt];    }    int mid=(l+r)>>1;    push_down(rt,(r-l+1));//向下传递     long long ans=0;    if (ql<=mid){//如果有查询的区间有一部分在当前节点的左孩子         ans+=query(rt*2,l,mid,ql,qr);    }    if (qr>mid){//有部分查询的区间在当前节点的右孩子         ans+=query(rt*2+1,mid+1,r,ql,qr);    }    push_up(rt);//向上更新     return ans;}//在区间[ul,ur]加上val void update(int rt,int l,int r,int ul,int ur,int val){    if (ul<=l&&r<=ur){//当前的区间包括在查询的区间之内         setv[rt]+=val;        sum[rt]+=(long long)(r-l+1)*val;    }else{        push_down(rt,r-l+1);//如果没有全部包括则向下更新         int mid=(l+r)>>1;        if (ul<=mid){            update(rt*2,l,mid,ul,ur,val);        }        if (mid<ur) {            update(rt*2+1,mid+1,r,ul,ur,val);        }        push_up(rt);    }}int main (){    while (scanf ("%d%d",&n,&q)!=EOF){        build(1,1,n);//建树         char ch[10];        long long a,b,val;        while (q--){            scanf ("%s",ch);            if (ch[0]=='C'){                scanf ("%lld%lld%lld",&a,&b,&val);                update(1,1,n,a,b,val);//更新             }else {                scanf ("%d%d",&a,&b);                long long ans=query(1,1,n,a,b);//查询                 printf ("%lld\n",ans);            }        }    }    return 0;}
阅读全文
0 0
原创粉丝点击