poj3468 A Simple Problem with Integers 线段树 延时更新

来源:互联网 发布:科来网络 编辑:程序博客网 时间:2024/06/07 23:42

A Simple Problem with IntegersTime Limit:5000MS    Memory Limit:131072KB    64bit IO Format:%I64d & %I64u

SubmitStatus

Description

给出了一个序列,你需要处理如下两种询问。

"C a bc"表示给[a, b]区间中的值全部增加c (-10000 c  10000)

"Q a b"询问[a, b]区间中所有值的和。

Input

第一行包含两个整数N,Q。1 N,Q  100000.

第二行包含n个整数,表示初始的序列A (-1000000000 Ai 1000000000)。

接下来Q行询问,格式如题目描述。

Output

对于每一个Q开头的询问,你需要输出相应的答案,每个答案一行。

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

很明显的线段树的题目,因为在修改的时候是区间修改,这种修改相对于单点修改更加消耗时间,因此需要使用延时更新,说白了就是在更新的时候加入找到一个区间满足条件,那么只修改这个区间点的值,并且设置其标志位表示其子区间还没有被更新,等到再次更新或者查询的时候,需要用到它的子区间了,再更新,注意,这种延时是会累加的,即上次未更新设置的值和这次未更新设置的值会累加。


#include <iostream>#include <stdio.h>#define maxn 100000#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1typedef long long ll;using namespace std;ll add[maxn<<2];//延时更新标志位ll sum[maxn<<2];void push_up(ll rt){    sum[rt]=sum[rt<<1]+sum[rt<<1|1];}void push_down(ll rt,ll num)//向下更新{    if(add[rt])    {        add[rt<<1]+=add[rt];//设置子区间标志位        add[rt<<1|1]+=add[rt];        sum[rt<<1]+=add[rt]*(num-(num>>1));//更新子区间        sum[rt<<1|1]+=add[rt]*(num>>1);        add[rt]=0;//重置标志位    }}void build(ll l,ll r,ll rt){    add[rt]=0;    if(l==r)    {        scanf("%lld",&sum[rt]);        return;    }    ll m=(l+r)>>1;    build(lson);    build(rson);    push_up(rt);}void update(ll L,ll R,ll data,ll l,ll r,ll rt){    if(L<=l&&R>=r)    {        add[rt]+=data;        sum[rt]+=data*(r-l+1);        return;    }    push_down(rt,r-l+1);//需要用到子区间,向下更新    ll m=(l+r)>>1;    if(L<=m)        update(L,R,data,lson);    if(R>m)        update(L,R,data,rson);    push_up(rt);}ll query(ll L,ll R,ll l,ll r,ll rt){    if(L<=l&&R>=r)    {        return sum[rt];    }    push_down(rt,r-l+1);//需要用到子区间,向下更新    ll res=0;    ll m=(l+r)>>1;    if(L<=m)        res+=query(L,R,lson);    if(R>m)        res+=query(L,R,rson);    return res;}int main(){    ll n,q;    char op[2];    ll parm[3];    scanf("%lld%lld",&n,&q);    build(1,n,1);    while(q--)    {        scanf("%s%lld%lld",op,&parm[0],&parm[1]);        switch(op[0])        {        case 'Q':            printf("%lld\n",query(parm[0],parm[1],1,n,1));            break;        case 'C':            scanf("%lld",&parm[2]);            update(parm[0],parm[1],parm[2],1,n,1);            break;        }    }    return 0;}





0 0
原创粉丝点击