# 牛客练习赛28 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

## 输出描述:

``对于每一个操作1,2，输出一行表示答案``

## 输入

``````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``````

## 备注:

``````对于100%的数据 n=10000,m=200000 (注意是等于号)

``````#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 10010;
int n, m;
struct SegmentTree{
int l, r;
ll sum1, sum2, add, mul;
#define l(p) t[p].l
#define r(p) t[p].r
#define sum1(p) t[p].sum1
#define sum2(p) t[p].sum2
#define mul(p) t[p].mul
}t[maxn<<2];
ll a[maxn];
void push_up(int p){
sum1(p) = sum1(p<<1) + sum1(p<<1|1);
sum2(p) = sum2(p<<1) + sum2(p<<1|1);
}
void push_down(int p){
if(mul(p) != 1){
mul(2*p) *= mul(p);
mul(2*p+1) *= mul(p);
sum1(2*p) *= mul(p);
sum1(2*p+1) *= mul(p);
sum2(2*p) *= (mul(p)*mul(p));
sum2(2*p+1) *= (mul(p)*mul(p));
mul(p) = 1;
}
}
}
void build(int p, int l, int r){
l(p) = l, r(p) = r;
add(p) = 0, mul(p) = 1;
if(l == r){
sum1(p) = a[l];
sum2(p) = a[l] * a[l];
return ;
}
int mid = (l+r)>>1;
build(2*p, l, mid);
build(2*p+1, mid+1, r);
push_up(p);
}
void change(int p, int l, int r, int c, int op){
if(l <= l(p) && r >= r(p)){
if(op == 3){
mul(p) = mul(p)*c;
sum1(p) = sum1(p)*c;
sum2(p) = sum2(p)*c*c;
}else{
sum2(p) += (r(p)-l(p)+1)*c*c + 2*sum1(p)*c;
sum1(p) += (r(p)-l(p)+1)*c;
}
return ;
}
push_down(p);
int mid = (l(p)+r(p)) / 2;
if(l <= mid) change(2*p, l, r, c, op);
if(r > mid) change(2*p+1, l, r, c, op);
push_up(p);
}
ll ask(int p, int l, int r, int op){
if(l <= l(p) && r >= r(p)){
if(op == 1) return sum1(p);
if(op == 2) return sum2(p);
}
push_down(p);
int mid = (l(p)+r(p))/2;
ll sum = 0;
if(l <= mid) sum += ask(2*p, l, r, op);
if(r > mid) sum += ask(2*p+1, l, r, op);
return sum;
}
int main()
{
scanf("%d %d", &n, &m);
for(int i = 1; i <= n; i++){
scanf("%lld\n", &a[i]);
}
build(1, 1, n);
int op, l, r, x;
while(m--){
scanf("%d %d %d", &op, &l, &r);
if(op == 1){
printf("%lld\n", ask(1, l, r, 1));
}else if(op == 2){
printf("%lld\n", ask(1, l, r, 2));
}else if(op == 3){
scanf("%d", &x);
change(1, l, r, x, 3);
}else{
scanf("%d", &x);
change(1, l, r, x, 4);
}
}
return 0;
}
``````

原文作者：B树
原文地址: https://blog.csdn.net/qq_37867156/article/details/82947597
本文转自网络文章，转载此文章仅为分享知识，如有侵权，请联系博主进行删除。