牛客练习赛28 B (复习线段树~)

Description:

链接:https://ac.nowcoder.com/acm/contest/200/B
来源:牛客网

    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

Input:

n,m

opi  li ri xi (for i=1...m)

Output:

answers

Analysis:

sum1[i] 表示区间和,sum2[i]表示区间平方和

add[i]表示同加延迟标记,mul[i]表示同乘延迟标记

注意更新延迟标记的时候,mul会对add产生影响

ReferenceO_O:https://blog.csdn.net/pall_scall/article/details/82951022

#define _CRT_SECURE_NO_WARNINGS  
#include<iostream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<sstream>
#include<cmath>
#include<iterator>
#include<bitset>
#include<stdio.h>
#include<unordered_set>
#include<ctime>
#include<cstring>
using namespace std;
#define _for(i,a,b) for(int i=(a);i<(b);++i)
#define _rep(i,a,b) for(int i=(a);i<=(b);++i)
typedef long long LL;
const int INF = 1 << 30;
const int maxn = 10005;
const int MOD = 1e9+7;
const double eps = 1e-6;

#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
const int M = 301, B = 500;

int n, m;
LL add[maxn << 2], mul[maxn << 2], sum1[maxn << 2], sum2[maxn << 2];
LL a[maxn];

void Pushup(int rt) {
	sum1[rt] = sum1[rt << 1] + sum1[rt << 1 | 1];
	sum2[rt] = sum2[rt << 1] + sum2[rt << 1 | 1];
}

void Build(int l,int r,int rt) {
	sum1[rt] = sum2[rt] = 0;
	add[rt] = 0; mul[rt] = 1;
	if (l == r) {
		sum1[rt] = a[l];
		sum2[rt] = a[l] * a[r];
		return;
	}
	int mid = (l + r) >> 1;
	Build(lson);
	Build(rson);
	Pushup(rt);
}

void Pushdown(int rt, int len) {
	add[rt << 1] = add[rt] + add[rt << 1] * mul[rt];
	add[rt << 1 | 1] = add[rt] + add[rt << 1 | 1] * mul[rt];
	sum2[rt << 1] += 2 * add[rt] * sum1[rt << 1] + (len - (len >> 1))*add[rt] * add[rt];
	sum2[rt << 1 | 1] += 2 * add[rt] * sum1[rt << 1 | 1] + (len >> 1)*add[rt] * add[rt];
	sum1[rt << 1] = add[rt] * (len - (len >> 1)) + sum1[rt << 1] * mul[rt];
	sum1[rt << 1 | 1] = add[rt] * (len >> 1) + sum1[rt << 1 | 1] * mul[rt];
	mul[rt << 1] *= mul[rt];
	mul[rt << 1 | 1] *= mul[rt];
	mul[rt] = 1;
	add[rt] = 0;
}

void Update(int l, int r, int rt, int L, int R, int val, int type) {
	if (l >= L && r <= R) {
		if (type == 3) {
			mul[rt] *= val;
			add[rt] *= val;
			sum1[rt] *= val;
			sum2[rt] *= (val*val);
			return;
		}
		else {
			add[rt] += val;
			sum2[rt] += (2 * val*sum1[rt] + val * val*(r - l + 1));
			sum1[rt] += (val*(r - l + 1));
			return;
		}
	}
	Pushdown(rt, r - l + 1);
	int mid = (l + r) >> 1;
	if (L <= mid) Update(lson, L, R, val, type);
	if (R > mid) Update(rson, L, R, val, type);
	Pushup(rt);

}

LL q1, q2,res;

void Query(int l, int r, int rt, int L, int R) {
	if (l >= L && r <= R) {
		q1 += sum1[rt];
		q2 += sum2[rt];
		return;
	}
	int mid = (l + r) >> 1;
	res = 0;
	Pushdown(rt, r - l + 1);
	if (L <= mid) Query(lson, L, R);
	if (R > mid) Query(rson, L, R);
}

int main()
{
	//freopen("C:\\Users\\admin\\Desktop\\in.txt", "r", stdin);
	//freopen("C:\\Users\\admin\\Desktop\\out.txt", "w", stdout);
	
	ios_base::sync_with_stdio(0);//用这个
	cin.tie(0);                    //就能防止cin超时orz

	while (cin >> n >> m) {
		_rep(i, 1, n) {
			cin >> a[i];
		}
		Build(1, n, 1);
		int op, l, r;
		LL v;
		while (m--) {
			cin >> op;
			q1 = q2 = res = 0;
			int l, r, x;
			if (op == 1) {
				cin >> l >> r;
				Query(1, n, 1, l, r);
				cout << q1 << endl;
			}
			else if (op == 2) {
				cin >> l >> r;
				Query(1, n, 1, l, r);
				cout << q2 << endl;
			}
			else if (op == 3) {
				cin >> l >> r >> x;
				Update(1, n, 1, l, r, x, 3);
			}
			else {
				cin >> l >> r >> x;
				Update(1, n, 1, l, r, x, 4);
			}
		}

	}


	return 0;
}

猜你喜欢

转载自blog.csdn.net/tomandjake_/article/details/87092698