首页 > 代码库 > POJ 3468 A Simple Problem with Integers 【树状数组】
POJ 3468 A Simple Problem with Integers 【树状数组】
题目链接:http://poj.org/problem?id=3468
题目大意:给出一组数组v[i],有两种操作,一种给出两个数a,b,要求输出v[a]到v[b]之间的和,另一种给出三个数a,b,c,让v[a]到v[b]之间的数全都加上c。
完全是树状数组能够实现的功能,但是如果就这样单纯的套用模板,做第二种操作是更新每个值,这样的操作就有可能超时。
换一种思路,既然第二种操作是给某区间上的所有数加上相同的值,那么应该是能够简化的才对。
假设数组sum[i]为原数组从v[1]到v[i]的和,数组c1[i]为更新之后,v[i]到v[n]的增加量,分析一下结果ans:
a,b之间的和ans=sum[b]-sum[a-1]+c1[1]*x + c1[2]*(x-1) + c1[3]*(x-2)+...+c1[x]*1
ans=sum[b]-sum[a-1]+segema(c1[i]*(x-i+1))
ans=sum[b]-sum[a-1] + (x+1)*segma(c1[i]) - segma(c1[i]*i)
令c2[i]=c1[i]*i;
如此便能利用树状数组解出此题
代码:
#include <stdio.h> #define N 100001 #define lowbit(i) ( i & (-i) ) int n; __int64 v[N]; __int64 c1[N];// 每个C数组代表v[i-lowbit(i)+1]到v[i]之间的和 __int64 c2[N]; __int64 sum[N]; void Updata(__int64 *array,__int64 i,__int64 a) { for(;i<=n;i+=lowbit(i)) array[i]+=a; } __int64 Sumv(__int64 *array,__int64 i) //求出数组v[1]到v[i]的和 { __int64 result=0; while (i>=1) { result+=array[i]; i-=lowbit(i); } return result; } int main() { __int64 q,i=0; __int64 ans=0; scanf("%I64d%I64d",&n,&q); for(i=1;i<=n;i++) scanf("%I64d",&v[i]); for(__int64 i=1;i<=n;i++) sum[i]=sum[i-1]+v[i]; while(q--) { char ch[2]; scanf("%s",ch); if(ch[0]=='Q') { __int64 s,t; scanf("%I64d%I64d",&s,&t); ans=sum[t]-sum[s-1]; ans+=((t+1)*Sumv(c1,t)-Sumv(c2,t)); ans-=(s*Sumv(c1,s-1)-Sumv(c2,s-1)); printf("%I64d\n",ans); } else { __int64 a,b,c; scanf("%I64d%I64d%I64d",&a,&b,&c); Updata(c1,a,c); Updata(c1,b+1,-c); Updata(c2,a,c*a); Updata(c2,b+1,-c*(b+1)); } } return 0; }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。