Time Limit: 5000MS Memory Limit: 131072K
Total Submissions: 122283 Accepted: 37929
Case Time Limit: 2000MS
Description
You have N integers, A1, A2, … , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.
Input
The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.
The second line contains N numbers, the initial values of A1, A2, … , AN. -1000000000 ≤ Ai ≤ 1000000000.
Each of the next Q lines represents an operation.
“C a b c” means adding c to each of Aa, Aa+1, … , Ab. -10000 ≤ c ≤ 10000.
“Q a b” means querying the sum of Aa, Aa+1, … , Ab.
Output
You need to answer all Q commands in order. One answer in a line.
Sample Input
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
Sample Output
4
55
9
15
Hint
The sums may exceed the range of 32-bit integers.
分析:
首先不考虑原始的情况,我们只考虑区间更新过后带来的影响的话,首先对于询问一个区间当中的元素和的话,肯定就是这个区间的原始的元素和,加上区间更新后所带来的影响,所以我们用a[]数组来保存前i个元素的和。
然后考虑区间更新所带来的影响,采用差分的思想,
设原数组第i位的值为ai,di=ai−a[i−1],则有(这里认为a0=0,此时的a表示的是数组中的原始值,与代码中的a不一样):
于是我们把原数组差分后维护两个树状数组,一个维护di,一个维护di×i。
这样区间求和时可以在两个树状数组中查询得到前缀和,区间修改时就是差分数组的修改,每次修改两个点即可。
其中c[i]维护的是d[i],c1[i]维护的是d[i]×i。
但是这里的c[]和c1[]都是差分数组,保存的也就只是更新所带来的值的变化,但因为这里要求的是在原来的基础上更新后的区间和,所以最终还要加上最原始的区间和。
#include
#include
#include
#include
using namespace std;
long long int a[510000],c[510000],cc[510000];
int n,m;
int lowbit(int x)
{
return x&(-x);
}
void update(long long int x,long long int v)
{
for(long long int i=x;i<=n;i+=lowbit(i))
{
c[i]+=v;
cc[i]+=(long long )x*v;
}
}
long long int sum(long long int x)
{
long long int ans=0;
for(int i=x;i;i-=lowbit(i))
ans+=(x+1)*c[i]-cc[i];
return ans+a[x];
}
int main()
{
char ch;
long long int s,r,va,num;
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(a,0,sizeof(a));
memset(c,0,sizeof(c));
memset(cc,0,sizeof(cc));
for(int i=1;i<=n;i++)
{
scanf("%lld",&num);
a[i]+=a[i-1]+num;
}
for(int i=0;iscanf("%c",&ch);
if(ch=='Q')
{
scanf("%lld%lld",&s,&r);
printf("%lld\n",sum(r)-sum(s-1));
}
else
{
scanf("%lld%lld%lld",&s,&r,&va);
update(s,va);
update(r+1,-va);
}
}
}
return 0;
}
#include
#include
#include
#include
using namespace std;
struct node
{
long long int sum,va;
}no[300000];
void pu(int t)
{
no[t].sum=no[t<<1].sum+no[t<<1|1].sum;
}
void build(int l,int r,int s)
{
no[s].va=0;
if(l==r)
{
scanf("%lld",&no[s].sum);
return ;
}
int mid=(l+r)>>1;
build(l,mid,s<<1);
build(mid+1,r,s<<1|1);
pu(s);
}
void dd(int t,int m)
{
if(no[t].va)
{
no[t<<1].va+=no[t].va;
no[t<<1|1].va+=no[t].va;
no[t<<1].sum+=(long long int)(m-(m>>1))*no[t].va;
no[t<<1|1].sum+=(long long int)(m>>1)*no[t].va;
no[t].va=0;
}
}
long long int query(int l,int r,int ll,int rr,int s)
{
if(l<=ll&&rr<=r)
return no[s].sum;
int mid=(ll+rr)>>1;
dd(s,rr-ll+1);
long long int ans=0;
if(l<=mid)
ans+=query(l,r,ll,mid,s<<1);
if(r>mid)
ans+=query(l,r,mid+1,rr,s<<1|1);
return ans;
}
void up(int l,int r,int add,int ll,int rr,int t)
{
if(l<=ll&&rr<=r)
{
no[t].sum+=(long long int )add*(rr-ll+1);
no[t].va+=add;
return ;
}
dd(t,rr-ll+1);
int mid=(ll+rr)>>1;
if(l<=mid)
up(l,r,add,ll,mid,t<<1);
if(mid1,rr,t<<1|1);
pu(t);
}
int main()
{
int n,q,a,b;
long long int c;
scanf("%d%d",&n,&q);
build(1,n,1);
char s[3];
while(q--)
{
scanf("%s",s);
if(s[0]=='Q')
{
cin>>a>>b;
cout<1,n,1)<else if(s[0]=='C')
{
cin>>a>>b>>c;
up(a,b,c,1,n,1);
}
}
return 0;
}