您的位置:首页 > 其它

POJ 3468 A Simple Problemwith Integers(线段树:区间add,区间查询)

2016-02-25 20:54 417 查看
思路:线段树的区间add和区间查询模板

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define LL long long
#define lson i*2,l,m
#define rson i*2+1,m+1,r
const int maxn = 100000+100;

LL sum[maxn*4];
LL addv[maxn*4];
void PushDown(int i,int num)
{
if (addv[i])
{
sum[i*2] +=addv[i]*(num-(num/2));
sum[i*2+1]+= addv[i]*(num/2);
addv[i*2] +=addv[i];
addv[i*2+1]+=addv[i];
addv[i]=0;
}
}
void PushUp(int i)
{
sum[i] = sum[i*2]+sum[i*2+1];
}

void build(int i,int l,int r)
{
addv[i]=0;
if (l==r)
{
scanf("%lld",&sum[i]);
return;
}
int m = (l+r)/2;
build(lson);
build(rson);
PushUp(i);
}
void update(int ql,int qr,int add,int i,int l,int r)
{
if (ql<=l && qr>=r)
{
addv[i]+=add;
sum[i]+=(LL)add*(r-l+1);
return;
}
PushDown(i,r-l+1);
int m = (l+r)/2;
if (ql <=m)
update(ql,qr,add,lson);
if (qr > m)
update(ql,qr,add,rson);
PushUp(i);
}

LL query(int ql,int qr,int i,int l,int r)
{
if (ql<=l && r<=qr)
{
return sum[i];
}
PushDown(i,r-l+1);
int m = (l+r)/2;
LL ans = 0;
if (ql <=m)
ans +=query(ql,qr,lson);
if (m<qr)
ans+=query(ql,qr,rson);
return ans;
}

int main()
{
int n,q;
while (scanf("%d%d",&n,&q)!=EOF && n&&q)
{
build(1,1,n);
while (q--)
{
char str[10];
scanf("%s",str);
int x,y,z;
if (str[0] =='Q')
{
scanf("%d%d",&x,&y);
printf("%lld\n",query(x,y,1,1,n));
}
else
{
scanf("%d%d%d",&x,&y,&z);
update(x,y,z,1,1,n);
}
}
}
}


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
15
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: