POJ 3468(树状数组+区间修改)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 3468(树状数组+区间修改)相关的知识,希望对你有一定的参考价值。


题目描述

给定一个长度为N的数列A,以及M条指令,每条指令可能是以下两种之一:

1、“C l r d”,表示把 A[l],A[l+1],…,A[r] 都加上 d。

2、“Q l r”,表示询问 数列中第 l~r 个数的和。

对于每个询问,输出一个整数表示答案。

输入格式

第一行两个整数N,M。

第二行N个整数A[i]。

接下来M行表示M条指令,每条指令的格式如题目描述所示。

输出格式

对于每个询问,输出一个整数表示答案。

每个答案占一行。

数据范围

1≤N,M≤10^5,
|d|≤10000|,
|A[i]|≤1000000000|

样例

输入样例: 10 5 1 2 3 4 5 6 7 8 9 10 Q 4 4 Q 1 10 Q 2 4 C 3 6 3 Q 2 4 输出样例: 4 55 9 15


AC代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<stdlib.h>
#include<queue>
#include<map>
#include<iomanip>
#include<math.h>
using namespace std;
typedef long long ll;
typedef double ld;
#define lowbit(x) x&(-x)
const int N=2e5+10;
ll c1[N],c2[N],n,m,a[N];
ll add(ll x,ll y)

for(ll i=x;i<=n;i+=lowbit(i))

c1[i]+=y;
c2[i]+=x*y;


ll ask(ll x)

ll ans=0;
for(ll i=x;i;i-=lowbit(i))
ans+=(x+1) *c1[i]-c2[i];
return ans;

int main()

scanf("%lld %lld\\n",&n,&m);
for(ll i=1;i<=n;i++)

scanf("%lld",&a[i]);
add(i,a[i]);
add(i+1,-a[i]);

getchar();
while(m--)

char ch=getchar();
if (ch==Q)

ll x,y;
scanf("%lld %lld\\n",&x,&y);
cout<<ask(y)-ask(x-1)<<endl;

if (ch==C)

ll x,y,d;
scanf("%lld %lld %lld\\n",&x,&y,&d);
add(x,d);
add(y+1,-d);


return 0;

另一种写法:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<stdlib.h>
#include<queue>
#include<map>
#include<iomanip>
#include<math.h>
using namespace std;
typedef long long ll;
typedef double ld;
#define lowbit(x) x&(-x)
const int N=2e5+10;
ll c1[N],c2[N],n,m,q,i,a[N];
ll sum[N];


void add(ll x,ll d,ll *c)

for(;x<=n;x+=lowbit(x))

c[x]+=d;



ll ask(ll x,ll *c)

ll sum=0;
for(;x>0;x-=lowbit(x))

sum+=c[x];

return sum;


int main()

char op[3];
ll x,y,d;
scanf("%lld %lld",&n,&q);
memset(c1,0,sizeof c1);
memset(c2,0,sizeof c2);
for(i=1; i<=n; ++i)

scanf("%lld",sum+i);
sum[i]+=sum[i-1];

while(q--)

scanf("%s",op);
if(op[0] == C)

scanf("%lld%lld%lld",&x,&y,&d);
add(x,d,c1);
add(y+1,-d,c1);
add(x,x*d,c2);
add(y+1,-(y+1)*d,c2);

else

scanf("%lld %lld",&x,&y);
printf("%lld\\n",sum[y]-sum[x-1]+ask(y,c1)*(y+1)-ask(x-1,c1)*x-ask(y,c2)+ask(x-1,c2));


return 0;

 


 

以上是关于POJ 3468(树状数组+区间修改)的主要内容,如果未能解决你的问题,请参考以下文章

POJ 3468 A Simple Problem with Integers(树状数组区间更新)

高级数据结构--树状数组

高级数据结构--树状数组

POJ3468 splay

POJ 3468 A Simple Problem with Integers 树状数组

poj 3468 : A Simple Problem with Integers 线段树 区间修改