Time Limit: 5000MS | Memory Limit: 131072K | |
Total Submissions: 88754 | Accepted: 27587 | |
Case Time Limit: 2000MS |
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
Source
POJ Monthly--2007.11.25, Yang Yi
【题目分析】
线段树的基本操作 在加一个数时,并不是直接暴力更新而是打上标记。同时也要注意标记向下传的时间,否则效率会大大的降低。在poj上,我用C++提交同过了,但是用G++却TLE了。选择测试环境也是一种靠人品的东西。
#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
using namespace std;
struct node{
int l,r;
long long sum,temp;
}t[1400001];//初始的数组要开的大一些,防止爆炸
int data[400001];
void build(int l,int r,int num)
{
t[num].l=l; t[num].r=r;
if (l==r){
t[num].sum=data[l];
return ;
}
else {
int mid=(l+r)/2;
build(l,mid,num*2);
build(mid+1,r,num*2+1);
t[num].sum=t[num*2].sum+t[num*2+1].sum;
}
return ;
}
void updata(int num) //标记下传 ,不要和我说我的单词拼错了 我英语不好
{
t[num*2].temp+=t[num].temp;//注意是+=
t[num*2+1].temp+=t[num].temp;
t[num*2].sum+=(t[num*2].r-t[num*2].l+1)*t[num].temp;
t[num*2+1].sum+=(t[num*2+1].r-t[num*2+1].l+1)*t[num].temp;
t[num].temp=0;
}
long long dosum(int l,int r,int num)
{
if (t[num].r<l||t[num].l>r) return 0;
if (t[num].l>=l&&t[num].r<=r) return t[num].sum;
if (t[num].temp) updata(num);
return dosum(l,r,num*2)+dosum(l,r,num*2+1);
}
void change(int l,int r,int add,int num)
{
if (t[num].l>r||t[num].r<l) return ;
if (t[num].l>=l&&t[num].r<=r){
t[num].sum+=add*(t[num].r-t[num].l+1);
t[num].temp+=add;
return ;
}
if (t[num].temp) updata(num);
int mid=l+r;
change(l,r,add,num*2);
change(l,r,add,num*2+1);
t[num].sum=t[num*2].sum+t[num*2+1].sum;
return;
}
int main()
{
int n,q;
scanf("%d%d",&n,&q);
for (int i=1;i<=n;++i) scanf("%d",&data[i]);
build(1,n,1);
while(q--){
char ch;
int a,b,c;
cin>>ch;
if (ch=='C'){
cin>>a>>b>>c;
change(a,b,c,1);
}
if (ch=='Q'){
cin>>a>>b;
cout<<dosum(a,b,1)<<endl;
}
}
}