线段树之三

#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;
}

  

posted on 2011-07-17 01:58  sysu_mjc  阅读(102)  评论(0编辑  收藏  举报

导航