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
裸线段树区间更新的题, 但很恶心的一点是数据范围超int, 虽然定义了一部分long long最后还是wa, 找大神要了几组测试数据没毛病,断定是数据范围的问题, 但实在找不出哪出问题, 一气之下把int全部改为long long,3000msAC。。。。因为long long的原因可能有点慢了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 100100
using namespace std;
struct seg
{
long long val;//存区间权值
long long addmark;//延时标记
}segtree[N * 4 + 10];
long long a[N * 4];
void build(long long node, long long left, long long right);//建树
void updata(long long node, long long _start, long long _end, long long left, long long right, long long add);//更新
long long query(long long node, long long _start, long long _end, long long left, long long right);//区间询问
void pushdown(long long node, long long left, long long right, long long mid);//将延时标记向下传递
int main()
{
long long n, m;
scanf("%lld%lld", &n, &m);
for(long long i = 1; i <= n; i++)
{
scanf("%lld", &a[i]);
}
build(1, 1, n);
char cmd;
for(int i = 1; i <= m; i++)
{
scanf(" %c", &cmd);
if(cmd == 'Q')
{
long long x, y;
scanf("%lld%lld", &x, &y);
long long ans = query(1, 1 , n, x, y);
printf("%lld\n", ans);
}
else if(cmd == 'C')
{
long long x, y;
long long z;
scanf("%lld%lld%lld", &x, &y, &z);
updata(1, 1, n, x, y, z);
}
}
return 0;
}
void build(long long node, long long left, long long right)
{
segtree[node].addmark = 0;//将每个延时标记初值为0
if(left == right)
{
segtree[node].val = a[left];
return;
}
long long mid = (left + right) >> 1;
build(node * 2, left, mid);
build(node * 2 + 1, mid + 1, right);
segtree[node].val = segtree[node * 2].val + segtree[node * 2 + 1].val;
}
void updata(long long node, long long _start, long long _end, long long left, long long right, long long add)
{
if(_start > right || _end < left)
{
return;
}
else if(_start >= left && _end <= right)
{
segtree[node].addmark += add;//更新此区间延时标记
segtree[node].val += (_end - _start + 1) * add;//更新区间权值
return;
}
long long mid = (_start + _end) >> 1;
pushdown(node, _start, _end,mid);//每查询一个区间时顺带将延时标记向下传递,并清除此区间延时标记
updata(node * 2, _start, mid, left, right, add);//更新左右子区间
updata(node * 2 + 1, mid + 1, _end, left, right, add);
segtree[node].val = segtree[node * 2].val + segtree[node * 2 + 1].val;
}
long long query(long long node, long long _start, long long _end, long long left, long long right)
{
if(_start > right || _end < left)
{
return 0;
}
else if(_start >= left && _end <= right)
{
return segtree[node].val;
}
long long mid = (_start + _end) >> 1;
pushdown(node, _start, _end, mid);//每次询问某个区间时顺便将此区间延时标记向下更新
if(mid >= right)
{
return query(node * 2, _start, mid, left, right);
}
else if(mid < left)
{
return query(node * 2 + 1, mid + 1, _end, left, right);
}
long long q1 = query(node * 2, _start, mid, left, right);
long long q2 = query(node * 2 + 1, mid + 1, _end, left, right);
return q1 + q2;
}
void pushdown(long long node, long long left, long long right, long long mid)
{
if(segtree[node].addmark != 0)
{
segtree[node * 2].val += (segtree[node].addmark * (mid - left + 1));//将延时标记更新到区间权值上
segtree[node * 2 + 1].val += (segtree[node].addmark * (right - mid));
segtree[node * 2].addmark += segtree[node].addmark;//更新子节点延时标记
segtree[node * 2 + 1].addmark += segtree[node].addmark;
segtree[node].addmark = 0;//清除父节点延时标记
}
}