A Simple Problem with Integers
Time limit 5000 ms Case time limit 2000 ms Memory limit 131072 kB
给出了一个序列,你需要处理如下两种询问。
"C a b c"表示给[a, b]区间中的值全部增加c (-10000 ≤ c ≤ 10000)。
"Q a b" 询问[a, b]区间中所有值的和。
第一行包含两个整数N, Q。1 ≤ N,Q ≤ 100000.
第二行包含n个整数,表示初始的序列A (-1000000000 ≤ Ai ≤1000000000)。
接下来Q行询问,格式如题目描述。
对于每一个Q开头的询问,你需要输出相应的答案,每个答案一行。
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
4
55
9
15
这道题就加了个简单的延迟更新,代码如下:
#include<stdio.h>
#include<string.h>
#define LL long long
struct node
{
LL l,r;
LL mark;
LL mid,sum;
};
node a[100000*4];
void BuildTree(LL i,LL l,LL r)
{
a[i].l=l;
a[i].r=r;
a[i].mark=0;
if(l==r)
{
scanf("%lld",&a[i].sum);
return;
}
a[i].mid=(l+r)/2;
BuildTree(i*2,l,a[i].mid);
BuildTree(i*2+1,a[i].mid+1,r);
a[i].sum=a[i*2].sum+a[i*2+1].sum;
}
void PushDown(LL i) //往下更新
{
if(a[i].mark!=0)
{
a[i*2].sum+=(a[i*2].r-a[i*2].l+1)*a[i].mark;
a[i*2+1].sum+=(a[i*2+1].r-a[i*2+1].l+1)*a[i].mark;
a[i*2].mark+=a[i].mark;
a[i*2+1].mark+=a[i].mark;
a[i].mark=0;
}
}
void update(LL i,LL l,LL r,LL num)
{
if(a[i].l==l&&a[i].r==r)
{
a[i].mark+=num;
a[i].sum+=(r-l+1)*num;
return;
}
PushDown(i);
if(a[i].mid>=r)update(i*2,l,r,num);
else if(a[i].mid<l)update(i*2+1,l,r,num);
else
{
update(i*2,l,a[i].mid,num);
update(i*2+1,a[i].mid+1,r,num);
}
a[i].sum=a[i*2].sum+a[i*2+1].sum;
}
LL Query(LL i,LL l,LL r) //询问
{
if(a[i].l==l&&a[i].r==r)return a[i].sum;
PushDown(i);
if(a[i].mid>=r)return Query(i*2,l,r);
else if(a[i].mid<l)return Query(i*2+1,l,r);
else return Query(i*2,l,a[i].mid)+Query(i*2+1,a[i].mid+1,r);
}
int main()
{
LL N,Q,i,j;
LL a,b,c;
char str[3];
while(scanf("%lld %lld",&N,&Q)!=EOF)
{
BuildTree(1,1,N);
for(i=0;i<Q;i++)
{
scanf("%s",str);
if(strcmp(str,"C")==0)
{
scanf("%lld %lld %lld",&a,&b,&c);
update(1,a,b,c);
}
if(strcmp(str,"Q")==0)
{
scanf("%lld %lld",&a,&b);
printf("%lld\n",Query(1,a,b));
}
}
}
return 0;
}