A Simple Problem with Integers
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.
线段树模板题
#include<stack>
#include<cstdio>
using namespace std;
typedef long long ll;
#define rep(i,x,y) for(register int i=x;i<=y;++i)
#define gc getchar()
template<class T>
inline void read(T&x) {
x=0;
char ch=gc;
bool flag=0;
while(ch<'0'||ch>'9')flag|=(ch=='-'),ch=gc;
while(ch>='0'&&ch<='9')x=x*10+ch-48,ch=gc;
x=flag?-x:x;
}
const int maxn=100000+10;
int n,q;
ll val[maxn];
struct Node {
ll sum,add;//sum:[l,r] 区间总和,add: 儿子区间要加的数
//add只和儿子节点有关;
int l,r;
} t[maxn*3];//*2的话,数据50w时过不了
void build(int i,int x,int y) {//建树
t[i].add=0;
t[i].l=x,t[i].r=y;
if(x==y) {t[i].sum=val[x];return;}
int m=(x+y)>>1;
build(i<<1,x,m);
build((i<<1)|1,m+1,y);
t[i].sum=t[i<<1].sum+t[(i<<1)|1].sum;
}
inline void putdown(int i) {//将add下放到他的儿子里
t[i<<1].sum+=t[i].add*(t[i<<1].r-t[i<<1].l+1);//这里也能说明sum是区间总和,而与add无关。
//这里是乘t[i].add不是乘更新之后的t[i<<1].add,因为 //add只和儿子节点有关,t[i<<1].add是节点(i<<1)儿子们的
) t[i<<1].add+=t[i].add;
t[(i<<1)|1].sum+=t[i].add*(t[(i<<1)|1].r-t[(i<<1)|1].l+1);
t[(i<<1)|1].add+=t[i].add;
t[i].add=0;
}
ll sum(int i,int x,int y) {
if(t[i].l>=x&&t[i].r<=y)return t[i].sum;
if(t[i].add)putdown(i);//如果要查询儿子节点,则儿子加上add
ll ans=0;
int m=(t[i].r+t[i].l)>>1;
if(x<=m)ans+=sum(i<<1,x,y);
if(y>m)ans+=sum((i<<1)|1,x,y);
return ans;
}
void add(int i,int x,int y,int a) {//区间x,y上加上a
if(t[i].l>=x&&t[i].r<=y) {
t[i].add+=a;//子节点都要加
t[i].sum+=a*(t[i].r-t[i].l+1);//sum已更新,下次查询到该区间直接return sum;
return;
}
if(t[i].add)putdown(i);//如果要更新子节点,得先把add下放给子节点。
//不等价于下面两句。
//a+=t[i].add;
//t[i].add=0;
int m=(t[i].r+t[i].l)>>1;
if(x<=m)add(i<<1,x,y,a);
if(y>m)add((i<<1)|1,x,y,a);
t[i].sum=t[i<<1].sum+t[(i<<1)|1].sum;
}
int main() {
// freopen("in.txt","r",stdin);
read(n),read(q);
rep(i,1,n)read(val[i]);
build(1,1,n);
char ch;
int x,y,a;
rep(i,1,q) {
ch=getchar();
if(ch=='Q') {
read(x),read(y);
printf("%lld\n",sum(1,x,y));
} else {
read(x),read(y),read(a);
add(1,x,y,a);
}
}
return 0;
}