poj 3468A Simple Problem with Integers

来源:互联网 发布:杭州电魂网络 编辑:程序博客网 时间:2024/06/05 04:03

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 51 2 3 4 5 6 7 8 9 10Q 4 4Q 1 10Q 2 4C 3 6 3Q 2 4

Sample Output

455915

Hint

The sums may exceed the range of 32-bit integers.

这题是线段树成段更新,看别人代码想了很久。
思路:开一个结构体,含有左右边界l,r,这段区间线段总和sum,更新标志ans(整段区间内每个数要加的数值)。
每次一个区间更新(即加一个数value)的时候,从第一个线线段开始向下判断,如果更新的区间刚好是这条线段的区间,那么直接加上更新的数值value并返回,否则整段区间的sum值变为sum+(b-a+1)*value,再在子节点中找直到找到区间大小加好符合的时候,ans=ans+value,返回。
每一次询问,从第一个线段开始向下,如果区间刚好符合,那么返回区间的sum否则把这条线段的更新标志往子节点传,同时这条线段的更新标志变为0.这里我采用的是每一次更新就把每根点段的总和都保存在sum中,这样询问的时候就不用麻烦的加上b[i].ans*(b[i].r-b[i].l+1).


#include<stdio.h>#include<string.h>#define maxn 100005#define ll long longchar str[10];ll a[maxn];struct node{ll l,r,sum,ans;}b[4*maxn];void build(ll l,ll r,ll i){    ll mid;    b[i].l=l;    b[i].r=r;    b[i].ans=0;    if(b[i].l==b[i].r)    {       b[i].sum=a[l];       return;    }    mid=(l+r)/2;    build(l,mid,2*i);    build(mid+1,r,i*2+1);    b[i].sum=b[i*2].sum+b[i*2+1].sum;}void pushdown(int i){    if(b[i].ans){        b[i*2].ans+=b[i].ans;        b[i*2+1].ans+=b[i].ans;        b[i*2].sum+=b[i].ans*(b[i*2].r-b[i*2].l+1);        b[i*2+1].sum+=b[i].ans*(b[i*2+1].r-b[i*2+1].l+1);        b[i].ans=0;    }}void add(ll l,ll r,ll value,ll i){ll mid;if(b[i].l==l && b[i].r==r){   b[i].ans=b[i].ans+value;   b[i].sum+=(b[i].r-b[i].l+1)*value;   return;}pushdown(i);b[i].sum+=(r-l+1)*value; //这一句写了,下面第二句就不用写了,是同一个意思mid=(b[i].l+b[i].r)/2;if(l>mid)add(l,r,value,i*2+1);else if(r<=mid)add(l,r,value,i*2);else{   add(l,mid,value,i*2);   add(mid+1,r,value,i*2+1);}//b[i].sum=b[i*2].sum+b[i*2+1].sum;  ---2}ll question(ll l,ll r,ll i){ll mid;if(b[i].l==l && b[i].r==r){   return b[i].sum;}pushdown(i);mid=(b[i].l+b[i].r)/2;if(l>mid)return question(l,r,i*2+1);else if(r<=mid)return question(l,r,i*2);else if(l<=mid && r>mid)return question(l,mid,i*2)+question(mid+1,r,i*2+1);}int main(){ll n,m,c,d,e,i,j;while(scanf("%lld%lld",&n,&m)!=EOF){for(i=1;i<=n;i++)scanf("%lld",&a[i]);build(1,n,1);while(m--){scanf("%s",str);if(str[0]=='Q'){scanf("%lld%lld",&c,&d);printf("%lld\n",question(c,d,1));}else if(str[0]=='C'){scanf("%lld%lld%lld",&c,&d,&e);add(c,d,e,1);}}}return 0;}


0 0
原创粉丝点击