链接:https://www.nowcoder.com/acm/contest/200/B
来源:牛客网
qn姐姐最好了~
qn姐姐给你了一个长度为n的序列还有m次操作让你玩,
1 l r 询问区间[l,r]内的元素和
2 l r 询问区间[l,r]内的元素的平方 和
3 l r x 将区间[l,r]内的每一个元素都乘上x
4 l r x 将区间[l,r]内的每一个元素都加上x
第一行两个数n,m
接下来一行n个数表示初始序列
就下来m行每行第一个数为操作方法opt,
若opt=1或者opt=2,则之后跟着两个数为l,r
若opt=3或者opt=4,则之后跟着三个数为l,r,x
操作意思为题目描述里说的
对于每一个操作1,2,输出一行表示答案
示例1
复制
5 6
1 2 3 4 5
1 1 5
2 1 5
3 1 2 1
4 1 3 2
1 1 4
2 2 3
复制
15
55
16
41
线段树懒惰标记:
#include
#include
#include
using namespace std;
#define ll long long
const int maxm = 10005;
int a[maxm];
struct node
{
ll val, sb, sc, l, r, s2;
ll add, mdd;
}tr[maxm * 20];
void down(int num)
{
int l = tr[num].l, r = tr[num].r;
ll add = tr[num].add, mdd = tr[num].mdd;
if (add)
{
tr[num].s2 += 2 * tr[num].val*add + (r - l + 1)*add*add;
tr[num].val += add*(r - l + 1);
if (tr[num].l != tr[num].r)
{
down(num * 2), down(num * 2 + 1);
tr[num * 2].add = tr[num * 2 + 1].add = add;
}
tr[num].add = 0;
}
if (mdd > 1)
{
tr[num].val *= mdd;
tr[num].s2 *= (mdd*mdd);
if (tr[num].l != tr[num].r)
{
down(num * 2), down(num * 2 + 1);
tr[num * 2].mdd = tr[num * 2 + 1].mdd = tr[num].mdd;
}
tr[num].mdd = 1;
}
}
void build(int l, int r, int num)
{
tr[num].l = l, tr[num].r = r;
tr[num].add = 0, tr[num].mdd = 1;
if (l == r)
{
tr[num].val = a[l];
tr[num].s2 = a[l] * a[l];
tr[num].sb = tr[num].sc = 0;
tr[num].add = 0, tr[num].mdd = 1;
return;
}
int mid = (l + r) / 2;
build(l, mid, num * 2);
build(mid + 1, r, num * 2 + 1);
tr[num].val = tr[num * 2].val + tr[num * 2 + 1].val;
tr[num].s2 = tr[num * 2].s2 + tr[num * 2 + 1].s2;
}
void update(int l, int r, ll val, int num, int flag)
{
if (tr[num].add || tr[num].mdd > 1) down(num);
if (l == tr[num].l&&r == tr[num].r)
{
if (flag == 1) tr[num].add += val;
else tr[num].mdd *= val;
down(num);
return;
}
int mid = (tr[num].l + tr[num].r) / 2;
if (mid >= r) update(l, r, val, num * 2, flag);
else if (mid < l) update(l, r, val, num * 2 + 1, flag);
else
{
update(l, mid, val, num * 2, flag);
update(mid + 1, r, val, num * 2 + 1, flag);
}
down(num * 2), down(num * 2 + 1);
tr[num].val = tr[num * 2].val + tr[num * 2 + 1].val;
tr[num].s2 = tr[num * 2].s2 + tr[num * 2 + 1].s2;
}
ll query(int l, int r, int num, int flag)
{
if (tr[num].add || tr[num].mdd > 1) down(num);
if (tr[num].l >= l&&tr[num].r <= r)
{
if (flag == 1) return tr[num].val;
else return tr[num].s2;
}
int mid = (tr[num].l + tr[num].r) / 2;
ll ans = 0;
if (mid >= r)
ans += query(l, r, num * 2, flag);
else if (mid < l)
ans += query(l, r, num * 2 + 1, flag);
else
{
ans += query(l, mid, num * 2, flag);
ans += query(mid + 1, r, num * 2 + 1, flag);
}
return ans;
}
int main()
{
int n, i, j, k, sum, m, flag, l, r, x;
scanf("%d%d", &n, &m);
for (i = 1;i <= n;i++)
scanf("%d", &a[i]);
build(1, n, 1);
while (m--)
{
scanf("%d%d%d", &flag, &l, &r);
if (flag == 1 || flag == 2)
printf("%lld\n", query(l, r, 1, flag));
else
{
scanf("%d", &x);
if (flag == 3) update(l, r, x, 1, 2);
else update(l, r, x, 1, 1);
}
}
return 0;
}