题目描述
如题,已知一个数列,你需要进行下面两种操作:
1.将某区间每一个数加上x
2.求出某区间每一个数的和
输入输出格式
输入格式:
第一行包含两个整数N、M,分别表示该数列数字的个数和操作的总个数。
第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。
接下来M行每行包含3或4个整数,表示一个操作,具体如下:
操作1: 格式:1 x y k 含义:将区间[x,y]内每个数加上k
操作2: 格式:2 x y 含义:输出区间[x,y]内每个数的和
输出格式:
输出包含若干行整数,即为所有操作2的结果。
输入输出样例
输入样例#1: 复制
5 5
1 5 4 2 3
2 2 4
1 2 3 2
2 3 4
1 1 5 1
2 1 4
输出样例#1: 复制
11
8
20
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn = 100005;
int n, m,a[maxn*2];
struct tree
{
int left, right;//左端点,右端点
long long value, tag;//维护的值(这题的区间和)以及懒标志
}t[maxn*4];
void build(int p, int x, int y)//构建树
{
t[p].left = x;//第p个节点的左端点
t[p].right = y;//..右端点同上
if(t[p].left == t[p].right)//叶子
{
t[p].value = a[x];
return ;
}
int mid = (x + y)/2;
build(2*p, x, mid);//构造左子树
build(2*p + 1, mid +1, y);//构造右子树
t[p].value = t[2*p].value + t[2*p + 1].value;//改变维护的值
}
//其实懒标记是表示树节点表示的这一段区间数字要加,也就是左子树和右子树都要加
//但是现在暂时不加,因为询问的时候未必用到左子树或者右子树的区间
//要的时候再调用这个函数用懒标记去修改,即下传懒标记
void spread(int p)//懒标志下放
{
if(t[p].tag)
{
t[2*p].value += t[p].tag*(t[2*p].right - t[2*p].left + 1);//改变左孩子维护的值
t[2*p + 1].value += t[p].tag *(t[2*p + 1].right - t[2*p+1].left + 1);//同上
t[2*p].tag += t[p].tag;//放懒标记
t[2*p + 1].tag += t[p].tag;//同上
t[p].tag = 0;//父节点懒标记清零
}
}
void change(int p, int x, int y, int z)
{
if(x<=t[p].left && y >= t[p].right)//区间覆盖
{
t[p].value += (long long )z * (t[p].right - t[p].left + 1);//修改维护的值
t[p].tag += z;//打上懒标记
return ;
}
spread(p);//下方懒标记
int mid = (t[p].left + t[p].right) >> 1;
if(x <= mid)
change(2*p, x, y, z);//修改区间覆盖左孩子,修改左孩子
if(y > mid)//同理
change(2*p + 1, x, y, z);
t[p].value = t[p*2].value + t[2*p + 1].value;
}
long long sum(int p, int x, int y)
{
if(x <= t[p].left && y >= t[p].right)//区间覆盖
{
return t[p].value;
}
spread(p);//下方懒标记
long long cnt = 0;
int mid = (t[p].left + t[p].right) >> 1;
if(x <= mid)
cnt += sum(2*p, x, y);
if(y > mid)
cnt += sum(2*p + 1, x, y);
return cnt;
}
int main()
{
ios::sync_with_stdio(false);
cin>>n>>m;
for(int i = 1; i <= n; i++)
cin>>a[i];
int q, x, y,z;
build(1, 1, n);
/*for(int i =1; i <= 16; i++)
cout<<t[i].left<<" "<<t[i].right<<endl;
system("pause");*/
while(m--)
{
cin>>q;
if(q == 1)
{
cin>>x>>y>>z;
change(1, x, y, z);
}
else
{
cin>>x>>y;
cout<<sum(1, x, y)<<endl;
}
}
system("pause");
}