POJ 3468 A Simple Problem with Integers
给出了一个序列,你需要处理如下两种询问。
"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<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#define N 100010
#include<map>
#define ll long long
using namespace std;
/*
sum(1~k) 1到k项的和
sum(1~k)=c1+(c1+c2)+(c1+c2+c3)+....+(c1+c2+c3+..cn);
=k*c1+(k-1)*c2+(k-2)*c3+....cn
通项 (k-i+1)*ci
拆分 tree1 (k+1)ci tree2 i*ci
*/
ll n,m;
ll sum[100010];
ll tree1[100010],tree2[100010];
ll lowbit(ll w)
{
return w&-w;
}
ll add(ll w,ll x,ll *tree)
{
while(w<=n)
{
tree[w]+=x;
w+=lowbit(w);
}
}
ll Query(ll w,ll *tree)
{
ll ans=0;
while(w>0)
{
ans+=tree[w];
w-=lowbit(w);
}
return ans;
}
int main()
{
std::ios::sync_with_stdio(false);//需要加速 不然会 runtime
cin>>n>>m;
memset(sum,0,sizeof(sum));
memset(tree1,0,sizeof(tree1));
memset(tree2,0,sizeof(tree2));
for(ll i=1;i<=n;i++)
{
cin>>sum[i];
sum[i]=sum[i]+sum[i-1];
}
for(ll i=0;i<m;i++)
{
char ch;
cin>>ch;
if(ch=='Q')
{
ll a,b;
cin>>a>>b;
ll ans=sum[b]-sum[a-1];
ans+=(b+1)*(Query(b,tree1))-(a)*(Query(a-1,tree1));//添加
ans=ans-((Query(b,tree2))-(Query(a-1,tree2)));//减少
cout<<ans<<endl;
}
else if(ch=='C')
{
ll a,b,x;
cin>>a>>b>>x;
add(a,x,tree1);// 添加
add(b+1,-x,tree1);
add(a,a*x,tree2);// 减少
add(b+1,-(b+1)*x,tree2);
}
}
return 0;
}