| Time Limit: 5000MS | Memory Limit: 131072K | |
| Total Submissions: 82019 | Accepted: 25376 | |
| Case Time Limit: 2000MS | ||
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.
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
线段树的区间延迟更新,也就是每次更新不需要全部更新到每一个节点,只需要更新到有效的那一段区间就可以了,但是区间查询的时候,如果某一个分支的更新值没有更新到,但是需要查询这个位置的值时,就会出问题,所以,就需要一个动态更新的函数,在需要求某个位置维护的值的时候,就把这个位置需要更新的值分别更新到他的左右子树。这样分步更新,做到化整为零,只在需要的时候更新小的区间,大大节约了运行的时间
具体自己也不是特别熟练,还需要以后加深理解........
另外这个题,注意是64位的整数...........
#include<stdio.h>
#include<algorithm>
using namespace std;
typedef long long ll;
ll sumtree[400005],add[400005];
void pushdown(int rt,int len)//更新子树
{
if(add[rt])//如果需要更新
{
int tp=rt<<1,tm=len>>1;
add[tp]+=add[rt];add[tp|1]+=add[rt];//延迟的值加到左右子树上
sumtree[tp]+=add[rt]*(len-tm);//加上这个区间新增的总数值
sumtree[tp|1]+=add[rt]*tm;//同上
add[rt]=0;//标记值清空
}
}
void build(int rt,int l,int r)//建树
{
if(l==r)
{
scanf("%lld",&sumtree[rt]);
return;
}
int mid=(l+r)>>1,tp=rt<<1;
build(tp,l,mid);build(tp|1,mid+1,r);
sumtree[rt]=sumtree[tp]+sumtree[tp|1];
}
void update(int rt,int l,int r,int a,int b,int c)
{
if(l>=a&&r<=b)
{
add[rt]+=c;
sumtree[rt]+=(ll)c*(r-l+1);
return;
}
pushdown(rt,r-l+1);//每一次都判断和更新一下
int mid=(l+r)>>1,tp=rt<<1;
if(mid>=a)
{
update(tp,l,mid,a,b,c);
}
if(mid<b)
{
update(tp|1,mid+1,r,a,b,c);
}
sumtree[rt]=sumtree[tp]+sumtree[tp|1];//回溯时,把操作过的大区间更新为正确值
}
ll find(int rt,int l,int r,int a,int b)
{
if(l>=a&&r<=b)
{
return sumtree[rt];
}
pushdown(rt,r-l+1);//更新一下
int mid=(l+r)>>1,tp=rt<<1;ll ret=0;//注意类型
if(mid>=a)
{
ret+=find(tp,l,mid,a,b);
}
if(mid<b)
{
ret+=find(tp|1,mid+1,r,a,b);
}
return ret;
}
int main()
{
int t,n,m;
//freopen("shuju.txt","r",stdin);
scanf("%d%d",&n,&m);
{
build(1,1,n);
while(m--)
{
char s[10];int a,b,c;
scanf("%s%d%d",s,&a,&b);
if(s[0]=='Q')
{
printf("%lld\n",find(1,1,n,a,b));
}
else
{
scanf("%d",&c);
update(1,1,n,a,b,c);
}
}
}
return 0;
}

本文介绍了一种使用线段树解决区间更新与查询的问题,并通过一个具体的编程实例详细展示了如何实现区间延迟更新,以提高处理效率。

606

被折叠的 条评论
为什么被折叠?



