Description
给出了一个序列,你需要处理如下两种询问。
"C a b c"表示给[a, b]区间中的值全部增加c (-10000 ≤ c ≤ 10000)。
"Q a b" 询问[a, b]区间中所有值的和。
Input
第一行包含两个整数N, Q。1 ≤ N,Q ≤ 100000.
第二行包含n个整数,表示初始的序列A (-1000000000 ≤ Ai ≤ 1000000000)。
接下来Q行询问,格式如题目描述。
Output
对于每一个Q开头的询问,你需要输出相应的答案,每个答案一行。
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
给出了一个序列,你需要处理如下两种询问。
"C a b c"表示给[a, b]区间中的值全部增加c (-10000 ≤ c ≤ 10000)。
"Q a b" 询问[a, b]区间中所有值的和。
Input
第一行包含两个整数N, Q。1 ≤ N,Q ≤ 100000.
第二行包含n个整数,表示初始的序列A (-1000000000 ≤ Ai ≤ 1000000000)。
接下来Q行询问,格式如题目描述。
Output
对于每一个Q开头的询问,你需要输出相应的答案,每个答案一行。
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
这道题是对一个区间中所有点进行更新,然后求区间和。
#include<stdio.h>
#include<iostream>
#include<string.h>
#define MAXN 100000+10
using namespace std;
long long initsum[MAXN];
long long c1[MAXN],c2[MAXN];
int n;
int lowbit(int x)///利用计算机补码计算2^k(其中k为x二进制末尾0的个数)
{
return x&(-x);
}
void add(long long *c,int i,int val)///修改操作,更新C[i],如果A[i]发生改变,那么C[i]节点发生改变,C[i]的祖先也发生改变。
{
while(i<=n)
{
c[i]+=val;
i+=lowbit(i);
}
}
int sum(long long *c,int i)///计算前i项的和
{
int s=0;
while(i>0)
{
s+=c[i];
i-=lowbit(i);
}
return s;
}
int main()
{
int m,a,b,e,t;
long long ans;
char str[2];
while(~scanf("%d%d",&n,&m))
{
memset(c1,0,sizeof(c1));
memset(c2,0,sizeof(c2));
memset(initsum, 0, sizeof (initsum));
for(int i=1; i<=n; i++)
{
scanf("%d",&t);
initsum[i] = initsum[i-1] + t;
}
while(m--)
{
scanf("%s",str);
if(str[0]=='Q')
{
scanf("%d%d",&a,&b);
ans=initsum[b]-initsum[a-1];
ans+=(b+1)*sum(c1,b)-sum(c2,b);
ans-=(a*sum(c1,a-1)-sum(c2,a-1));
printf("%lld\n",ans);
}
else
{
scanf("%d%d%d",&a,&b,&e);
add(c1,a,e);
add(c2,a,a*e);///这两个add后,区间c[a...n]每个数都增加了c。
add(c1,b+1,-e);
add(c2,b+1,-(b+1)*e); ///这两个update后,区间c[b+1...n]每个数都减少了c
}
}
}
}