线段树 pku poj3468

题意是这样的

给你n个数    输入n个数为初值    询问Q次(1.把a到b加c    2.输出a到b的和)(数据范围很大  暴力可能超时    用int64处理)

这道题我是用线段树做的      这道题在于开两个数组  一个存当前节点累加和      另一个存总和      注意函数返回值为int64

  


贴一下AC代码!!!

#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
#define LL(x) (x<<1)
#define RR(x) (x<<1)|1


__int64 hash[4*100000],tree[4*100000],n;
__int64 update(__int64 left,__int64 right,__int64 L,__int64 R,__int64 c,__int64 mark)
{
if(left==L&&right==R)
{
hash[mark]+=c;
tree[mark]+=c*(R-L+1);
return tree[mark];
}
__int64 mid=(right+left)/2;
if(L>mid)
{
tree[mark]=tree[LL(mark)]+update(mid+1,right,L,R,c,RR(mark));
}
else if(R<=mid)
{
tree[mark]=update(left,mid,L,R,c,LL(mark))+tree[RR(mark)];
}
else
{
tree[mark]=update(left,mid,L,mid,c,LL(mark))+update(mid+1,right,mid+1,R,c,RR(mark));
}
return tree[mark];
}
__int64 find(__int64 left,__int64 right,__int64 L,__int64 R,__int64 mark,__int64 leap)
{
__int64 sum=0;
if(left==L&&right==R)
{
sum+=tree[mark]+leap*(R-L+1);
return sum;
}
__int64 mid=(left+right)/2;
if(L>mid)
{
sum+=find(mid+1,right,L,R,RR(mark),leap+hash[mark]);
}
else if(R<=mid)
{
sum+=find(left,mid,L,R,LL(mark),leap+hash[mark]);
}
else
{
sum+=find(left,mid,L,mid,LL(mark),leap+hash[mark])+find(mid+1,right,mid+1,R,RR(mark),leap+hash[mark]);
}
return sum;
}
int main()                   
{
__int64 i,j,a,b,c,Q;
char str[2];
while(~scanf("%I64d%I64d",&n,&Q))
{
memset(tree,0,sizeof(tree));
memset(hash,0,sizeof(hash));
for(i=1;i<=n;i++)
{
scanf("%I64d",&a);
update(1,n,i,i,a,1);
}
for(i=1;i<=Q;i++)
{
scanf("%s",str);
scanf("%I64d%I64d",&a,&b);
if(str[0]=='Q')
{
printf("%I64d\n",find(1,n,a,b,1,0));
}
else
{
scanf("%I64d",&c);
update(1,n,a,b,c,1);
}
}
}
return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值