您的位置:首页 > 其它

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

2015-11-10 02:55 323 查看
A Simple Problem with IntegersTime Limit:5000MS    Memory Limit:131072KB    64bit
IO Format:
%I64d & %I64u

SubmitStatus

Description

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

"C a b
c"表示给[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 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 <iostream>
#include <stdio.h>
#define maxn 100000
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息