B - A Simple Problem with Integers
Time Limit:5000MS Memory Limit:131072KB 64bit IO Format:%I64d & %I64u
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
比较奇怪的是,输入字符的时候不能定义一个字符变量来输入,必须的定义一个字符数组,不然就会无法运行,不知道为什么。区间更新的时候有一个节省时间的办法就是留一个标记点,如果需要计算到某点的子节点时才pushdown,否则直接跳过,直接取该点的值就可以了。
#include <iostream>
#include<cstdio>
using namespace std;
#define ll long long int
ll a[100010],add[100010*4];
struct node
{
ll left,right,sum;
}tree[100010*4];
void build(ll id,ll l,ll r)
{
tree[id].left=l;
tree[id].right=r;
if(l==r)
tree[id].sum=a[l];
else
{
ll mid=(l+r)/2;
build(id*2,l,mid);
build(id*2+1,mid+1,r);
tree[id].sum=tree[id*2].sum+tree[id*2+1].sum;
}
}
void pushdown(ll id)
{
if(add[id])
{
ll m=tree[id].right-tree[id].left+1;
add[id*2]+=add[id];
add[id*2+1]+=add[id];
tree[id*2].sum+=(m-m/2)*add[id];
tree[id*2+1].sum+=(m/2)*add[id];
add[id]=0;
}
}
ll query(ll id,ll l,ll r)
{
if(l<=tree[id].left&&tree[id].right<=r)
{
return tree[id].sum;
}
pushdown(id);
ll ret=0;
ll mid=(tree[id].left+tree[id].right)/2;
if(l<=mid) ret+=query(id*2,l,r);
if(r>mid) ret+=query(id*2+1,l,r);
return ret;
}
void update(ll id,ll l,ll r,ll c)
{
if(l<=tree[id].left&&tree[id].right<=r)
{
add[id]+=c;
tree[id].sum+=(ll)(tree[id].right-tree[id].left+1)*c;
return;
}
else
{
pushdown(id);
ll mid=(tree[id].left+tree[id].right)/2;
if(l<=mid) update(id*2,l,r,c);
if(r>mid) update(id*2+1,l,r,c);
tree[id].sum=tree[id*2].sum+tree[id*2+1].sum;
}
}
int main()
{
ll n,q;
scanf("%I64d%I64d",&n,&q);
for(ll i=1;i<=n;i++)
{
scanf("%I64d",&a[i]);
}
build(1,1,n);
ll x,y,c;
char z[2];
for(ll i=0;i<q;i++)
{
scanf("%s",z);
if(z[0]=='Q')
{
scanf("%I64d%I64d",&x,&y);
ll sum=query(1,x,y);
printf("%I64d\n",sum);
}
if(z[0]=='C')
{
scanf("%I64d%I64d%I64d",&x,&y,&c);
update(1,x,y,c);
}
}
return 0;
}