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(树状数组区间更新)