题目描述
已知一个数列,需要进行下面两种操作:
- 将某个区间的数加上k。
- 求出某区间每一个数的和。
输入格式
第一行包含两个整数 n , m 分别表示该数列数字的个数和操作的总个数。
第二行包含 n 个用空格分隔的整数,其中第 i 个数字表示数列第 i 项的初始值。
接下来 m 行每行包含 3 或 4 个整数,表示一个操作,具体如下:
x y k
:将区间 [ x, y ] 内每个数加上 kk。2 x y
:输出区间[ x , y ] 内每个数的和。
输出格式
输出包含若干行整数,即为所有操作 2 的结果。
输入输出样例
输入
5 5
1 5 4 2 3
2 2 4
1 2 3 2
2 3 4
1 1 5 1
2 1 4
输出
11
8
20
AC代码
#include <stdio.h>
#include <malloc.h>
#define MaxSize 100010
#define LL long long int
typedef struct node
{
int left, right;
LL sum, inc;
struct node* lchild, * rchild;
} node;
void buildtree(node* root, int left, int right, LL Num[])
{
root->left = left;
root->right = right;
root->inc = 0;
if (left != right)
{
root->lchild = (node*)malloc(sizeof(node));
buildtree(root->lchild, left, (left + right) / 2, Num);
root->rchild = (node*)malloc(sizeof(node));
buildtree(root->rchild, (left + right) / 2 + 1, right, Num);
root->sum = root->lchild->sum + root->rchild->sum;
}
else
{
root->sum = Num[left];
root->lchild = root->rchild = NULL;
}
}
void fixthetree(node* root, int left, int right, LL k)
{
if (root == NULL)
return;
if (root->left > right || root->right < left) return;
else if (root->left >= left && root->right <= right)
{
root->inc += k;
}
else if (root->left < left && root->right <= right)
{
root->sum += (root->right - left + 1) * k;
fixthetree(root->lchild, left, right, k);
fixthetree(root->rchild, left, right, k);
}
else if(root->left>=left&&root->right>right)
{
root->sum += (right - root->left + 1) * k;
fixthetree(root->lchild, left, right, k);
fixthetree(root->rchild, left, right, k);
}
else //if (root->left<left && root->right>right)
{
root->sum += (right - left + 1) * k;
fixthetree(root->lchild, left, right, k);
fixthetree(root->rchild, left, right, k);
}
}
LL CalcSum(node* root, int left, int right)
{
if (root == NULL)
return 0;
if (root->left > right || root->right < left) return 0;
else if (root->left >= left && root->right <= right)
{
return root->sum + (root->right - root->left + 1) * root->inc;
}
else if (root->left < left && root->right <= right)
{
return (root->right - left + 1) * root->inc + CalcSum(root->lchild, left, right) + CalcSum(root->rchild, left, right);
}
else if (root->left >= left && root->right > right)
{
return (right - root->left + 1) * root->inc + CalcSum(root->lchild, left, right) + CalcSum(root->rchild, left, right);
}
else //if (root->left<left && root->right>right)
{
return (right - left + 1) * root->inc + CalcSum(root->lchild, left, right) + CalcSum(root->rchild, left, right);
}
}
int main()
{
int n, m, op;
int left, right;
LL Num[MaxSize], k;
node* root = (node*)malloc(sizeof(node));
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i)
{
scanf("%lld", &Num[i]);
}
buildtree(root, 1, n, Num);
for (int i = 0; i < m; ++i)
{
scanf("%d", &op);
if (op == 1)
{
scanf("%d%d%lld", &left, &right, &k);
fixthetree(root, left, right, k);
}
else
{
scanf("%d%d", &left, &right);
printf("%lld\n", CalcSum(root, left, right));
}
}
return 0;
}