E - A Simple Problem with Integers
Time Limit:5000MS Memory Limit:131072KB 64bit IO Format:%I64d & %I64u
Submit
Status
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 abc” means adding c to each of Aa, Aa+1, … , Ab. -10000 ≤ c ≤ 10000.
“Q ab” 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
使用改段求段的模型,就是上一篇树状数组里面总结的第三种模型,时空复杂度都比用线段树的做更小~
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 100020;
long long a[MAXN];
long long B[MAXN];
long long C[MAXN];
int n,Q;
//改段求段型:
//【1】修改操作:将A[l..r]之间的全部元素值加上c;
//ADD_B(r, c); ADD_C(r, c);
//if (l > 1) {ADD_B(l - 1, -c); ADD_C(l - 1, -c);}
//【2】求和操作:求此时A[l..r]的和。
//SUM(r) - SUM(l - 1)。
void ADD_B(int x, int c)
{
for (int i=x; i>0; i-=i&(-i))
B[i] += c;
}
void ADD_C(int x, int c)
{
for (int i=x; i<=n; i+=i&(-i))
C[i] += x * c;
}
long long SUM_B(int x)
{
int s = 0;
for (int i=x; i<=n; i+=i&(-i))
s += B[i];
return s;
}
long long SUM_C(int x)
{
int s = 0;
for (int i=x; i>0; i-=i&(-i))
s += C[i];
return s;
}
inline long long SUM(int x)
{
if (x)
return SUM_B(x) * x + SUM_C(x - 1);
else
return 0;
}
int main()
{
while(scanf("%d%d",&n,&Q) != EOF)
{
memset(a,0,sizeof(a));
memset(B,0,sizeof(B));
memset(C,0,sizeof(C));
for(int i =1; i<=n;i++)
scanf("%I64d",&a[i]);
for(int i =1; i<=n;i++)
{
ADD_B(i,a[i]);ADD_C(i,a[i]);
if(i > 1){ADD_B(i-1,-a[i]); ADD_C(i-1,-a[i]);}
}
char ch[20];
int num1,num2,num3;
while(Q--)
{
scanf("%s",ch);
if(ch[0] == 'Q')
{
scanf("%d%d",&num1,&num2);
printf("%I64d\n",SUM(num2)-SUM(num1-1));
}
else if (ch[0] =='C')
{
scanf("%d%d%d",&num1,&num2,&num3);
ADD_B(num2,num3); ADD_C(num2,num3);
if (num1>1)
{
ADD_B(num1-1,-num3); ADD_C(num1-1,-num3);
}
}
}
}
return 0;
}