第一次做线段树的题目,之前看过一点线段树的内容,自以为懂了,结果一提交TLE后来上网看了知道了延迟更新,终于1600msA了
顺便说一下延迟更新问题,如果我们仔细观察线段树的更新操作,其实更新是o(L*lgN)级别的因为要更新到叶子为止
但是其实更新并不需要更新到叶子节点,只需要搜索到等大的区间时在此区间上做个标记即可,复杂度为o(lgN),比如更新[1,5]这个区间,只需要在[1,5]区间上(如果分成n个区间段就在各个区间段)上添加一个add_to_all的段,把值加到这个段上即可。
查的时候将add_to_all的值不断增加下推即可
给出代码
#include <stdio.h>
struct node
{
int right;
int left;
long long sum;
long long tototal;
}tree[1000000];
void init(int left,int right,int now,long long value,int des)
{
int middle=(left+right)>>1;
tree[now].left=left;
tree[now].right=right;
tree[now].sum+=value;
if (left != right)
{
if(des>middle)
{
init(middle+1,right,(now<<1)+2,value,des);
}
else
{
init(left,middle,(now<<1)+1,value,des);
}
}
return;
}
long long sum(int left,int right,int now)
{
int middle=(tree[now].left+tree[now].right)>>1;
if(left != tree[now].left || right != tree[now].right)
{
if(left > middle)
{
return sum(left,right,(now<<1)+2)+tree[now].tototal*(right-left+1);
}
else
{
if(right <= middle)
{
return sum(left,right,(now<<1)+1)+tree[now].tototal*(right-left+1);
}
else
{
return sum(left,middle,(now<<1)+1)+sum(middle+1,right,(now<<1)+2)+tree[now].tototal*(right-left+1);
}
}
}
else
{
return tree[now].sum+tree[now].tototal*(right-left+1);
}
}
void add(int left,int right,int now,int addvalue)
{
int middle=(tree[now].left+tree[now].right)>>1;
if(left == tree[now].left && right == tree[now].right)
{
tree[now].tototal+=addvalue;
return;
}
tree[now].sum+=addvalue*(right-left+1);
if(tree[now].left != tree[now].right)
{
if(left > middle)
{
add(left,right,(now<<1)+2,addvalue);
}
else
{
if(right <= middle)
{
add(left,right,(now<<1)+1,addvalue);
}
else
{
add(left,middle,(now<<1)+1,addvalue);
add(middle+1,right,(now<<1)+2,addvalue);
}
}
}
return;
}
int main()
{
int N,Q,i,a,b,addvalue;
long long value;
char tmp;
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
scanf("%d %d",&N,&Q);
for(i=0;i<N;++i)
{
scanf("%I64d",&value);
init(0,N-1,0,value,i);
}
for(i=0;i<Q;++i)
{
getchar();
scanf("%c %d %d",&tmp,&a,&b);
if('Q' == tmp)
{
printf("%I64d\n",sum(a-1,b-1,0));
}
else
{
scanf("%d",&addvalue);
add(a-1,b-1,0,addvalue);
}
}
return 0;
}