线段树之三
#include <iostream> //poj 3468 A Simple Problem with Integers
using namespace std;
struct segment
{
__int64 l,r,sum,off; //当覆盖范围为整个区间时,off记录此时的偏移量,默认为0
}tree[400000];
__int64 arr[100005],c; //数据类型 __int64 ,long long 都可以
void built_tree(__int64 n,__int64 s,__int64 t)
{
tree[n].l=s;tree[n].r=t;
if(s==t)
tree[n].sum=arr[s];
else
{
__int64 mid=(s+t)>>1;
built_tree(2*n,s,mid);
built_tree(2*n+1,mid+1,t);
tree[n].sum=tree[2*n].sum+tree[2*n+1].sum;
}
}
void modify(__int64 n,__int64 s,__int64 t)
{
tree[n].sum+=(t-s+1)*c;
if(s==tree[n].l&&t==tree[n].r)
tree[n].off+=c;
//当覆盖整个区间时,off 记录偏移量,而且不必再继续往下修改了。如果一直修改到叶子节点,即head==end 时,肯定TLE
else
{
__int64 mid=(tree[n].l+tree[n].r)>>1; //注意不要写成 __int64 mid=(s+t)>>1;
if(s<=mid)
modify(2*n,s,min(mid,t));
if(t>mid)
modify(2*n+1,max(mid+1,s),t); //注意不要写成 modify(2*n+1,max(mid,s),t);
//这里不用再写 tree[n].sum=tree[2*n].sum+tree[2*n+1].sum; 因为前面已经有 tree[n].sum+=(t-s+1)*c;
}
}
__int64 query(__int64 n,__int64 s,__int64 t)
{
if(s==tree[n].l&&t==tree[n].r) //当询问的范围为整个区间时,直接返回该区间的总和
return tree[n].sum;
else
{
__int64 mid=(tree[n].l+tree[n].r)>>1,a=0,b=0;
if(s<=mid)
a=query(2*n,s,min(mid,t));
if(t>mid)
b=query(2*n+1,max(mid+1,s),t);
return a+b+(t-s+1)*tree[n].off;
//要加上(t-s+1)*tree[n].off 的偏移量,因为如果之前修改了tree[n]整个区间,那么在tree[2*n].sum 或 tree[2*n+1].sum中是无法反映出来的
}
}
int main()
{
__int64 n,q,s,t;
scanf("%I64d%I64d",&n,&q);
char ch;
for(__int64 i=1;i<=n;++i)
scanf("%I64d",arr+i);
built_tree(1,1,n);
while (q--)
{
scanf(" %c",&ch); //不是scanf("%c",&ch);
if(ch=='Q')
{
scanf("%I64d%I64d",&s,&t);
printf("%I64d\n",query(1,s,t));
}
else
{
scanf("%I64d%I64d%I64d",&s,&t,&c);
modify(1,s,t);
}
}
return 0;
}
//去掉tree[]的范围参数l,r,其他一样
类似代码
#include <iostream>
using namespace std;
struct segment
{
__int64 sum,off; //当覆盖范围为整个区间时,off记录此时的偏移量,默认为0
}tree[400000];
__int64 arr[100005],c;
void built_tree(__int64 n,__int64 s,__int64 t)
{
if(s==t)
tree[n].sum=arr[s];
else
{
__int64 mid=(s+t)>>1;
built_tree(2*n,s,mid);
built_tree(2*n+1,mid+1,t);
tree[n].sum=tree[2*n].sum+tree[2*n+1].sum;
}
}
void modify(__int64 n,__int64 s,__int64 t,__int64 head,__int64 end)
{
tree[n].sum+=(t-s+1)*c;
if(s==head&&t==end)
tree[n].off+=c;
//当覆盖整个区间时,off 记录偏移量,而且不必再继续往下修改了。如果一直修改到叶子节点,即head==end 时,肯定TLE
else
{
__int64 mid=(head+end)>>1; //注意不要写成 __int64 mid=(s+t)>>1;
if(s<=mid)
modify(2*n,s,min(mid,t),head,mid);
if(t>mid)
modify(2*n+1,max(mid+1,s),t,mid+1,end);
//这里不用再写 tree[n].sum=tree[2*n].sum+tree[2*n+1].sum; 因为前面已经有 tree[n].sum+=(t-s+1)*c;
}
}
__int64 query(__int64 n,__int64 s,__int64 t,__int64 head,__int64 end)
{
if(s==head&&t==end) //当询问的范围为整个区间时,直接返回该区间的总和
return tree[n].sum;
else
{
__int64 mid=(head+end)>>1,a=0,b=0;
if(s<=mid)
a=query(2*n,s,min(mid,t),head,mid);
if(t>mid)
b=query(2*n+1,max(mid+1,s),t,mid+1,end);
return a+b+(t-s+1)*tree[n].off;
//要加上(t-s+1)*tree[n].off 的偏移量,因为如果之前修改了tree[n]整个区间,那么在tree[2*n].sum 或 tree[2*n+1].sum中是无法反映出来的
}
}
int main()
{
__int64 n,q,s,t;
scanf("%I64d%I64d",&n,&q);
char ch;
for(__int64 i=1;i<=n;++i)
scanf("%I64d",arr+i);
built_tree(1,1,n);
while (q--)
{
scanf(" %c",&ch); //不是scanf("%c",&ch);
if(ch=='Q')
{
scanf("%I64d%I64d",&s,&t);
printf("%I64d\n",query(1,s,t,1,n));
}
else
{
scanf("%I64d%I64d%I64d",&s,&t,&c);
modify(1,s,t,1,n);
}
}
return 0;
}
//如果一直修改到叶子节点,则TLE
TLE
#include <iostream> //TLE
using namespace std;
struct segment
{
__int64 sum;
}tree[400000];
__int64 arr[100005],c;
void built_tree(__int64 n,__int64 s,__int64 t)
{
if(s==t)
tree[n].sum=arr[s];
else
{
__int64 mid=(s+t)>>1;
built_tree(2*n,s,mid);
built_tree(2*n+1,mid+1,t);
tree[n].sum=tree[2*n].sum+tree[2*n+1].sum;
}
}
void modify(__int64 n,__int64 s,__int64 t,__int64 head,__int64 end)
{
if(s==t&&s==head&&t==end) //一直修改到叶子节点,TLE
tree[n].sum+=c;
else
{
__int64 mid=(head+end)>>1;
if(s<=mid)
modify(2*n,s,min(mid,t),head,mid);
if(t>mid)
modify(2*n+1,max(mid+1,s),t,mid+1,end);
tree[n].sum=tree[2*n].sum+tree[2*n+1].sum;
}
}
__int64 query(__int64 n,__int64 s,__int64 t,__int64 head,__int64 end)
{
if(s==head&&t==end)
return tree[n].sum;
else
{
__int64 mid=(head+end)>>1,a=0,b=0;
if(s<=mid)
a=query(2*n,s,min(mid,t),head,mid);
if(t>mid)
b=query(2*n+1,max(mid+1,s),t,mid+1,end);
return a+b;
}
}
int main()
{
__int64 n,q,s,t;
scanf("%I64d%I64d",&n,&q);
char ch;
for(__int64 i=1;i<=n;++i)
scanf("%I64d",arr+i);
built_tree(1,1,n);
while (q--)
{
scanf(" %c",&ch);
if(ch=='Q')
{
scanf("%I64d%I64d",&s,&t);
printf("%I64d\n",query(1,s,t,1,n));
}
else
{
scanf("%I64d%I64d%I64d",&s,&t,&c);
modify(1,s,t,1,n);
}
}
return 0;
}