##Segment Tree

馅断术模板啦~

已知一个数列,你需要进行下面三种操作:

  1. 将某区间每一个数乘上x

  2. 将某区间每一个数加上x

  3. 求出某区间每一个数的和

输入格式

第一行包含三个整数N、M、P,分别表示该数列数字的个数、操作的总个数和模数。

第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。

接下来M行每行包含3或4个整数,表示一个操作,具体如下:

操作1: 格式:1 x y k 含义:将区间[x,y]内每个数乘上k

操作2: 格式:2 x y k 含义:将区间[x,y]内每个数加上k

操作3: 格式:3 x y 含义:输出区间[x,y]内每个数的和对P取模所得的结果

输出格式

输出包含若干行整数,即为所有操作3的结果。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <memory.h>

#define ll long long 
using namespace std;

const int maxn = 100005;
const int maxm = 1000005;
ll a[maxn];
ll sum[maxm];
ll addv[maxm];
ll mulv[maxm];
int p;
inline ll read()
{
	char c = getchar(); ll x = 0;
	for (; !isdigit(c); c = getchar());
	for (; isdigit(c); c = getchar())
		x = x * 10 + (c - '0');
	return x;
}


void  cons(int o, int L, int R)
{
	addv[o] = 0;
	mulv[o] = 1;
	if (L == R)
		sum[o] = a[L];
	else
	{
		int mid = (L + R) / 2;
		cons(o * 2, L, mid);
		cons(o * 2 + 1, mid + 1, R);
		sum[o] = sum[o * 2] + sum[o * 2 + 1];
	}
	sum[o] %= p;
	return;
}


inline void maintain(int o, int L, int R)
{
	int mid = (L + R) / 2;
	sum[o * 2] = (sum[o * 2] * mulv[o] + addv[o] * (mid - L + 1)) % p;
	sum[o * 2 + 1] = (sum[o * 2 + 1] * mulv[o] + addv[o] * (R - mid)) % p;

	mulv[o * 2] = (mulv[o] * mulv[o * 2]) % p;
	mulv[o * 2 + 1] = (mulv[o] * mulv[o * 2 + 1]) % p;
	addv[o * 2] = (addv[o * 2] * mulv[o] + addv[o]) % p;
	addv[o * 2 + 1] = (addv[o * 2 + 1] * mulv[o] + addv[o]) % p;

	addv[o] = 0;
	mulv[o] = 1;
}


ll ql, qr;
void u_add(int o, int L, int R, int d)
{
	if (R<ql || L>qr)return;
	if (ql <= L && R <= qr)
	{
		addv[o] = (addv[o] + d) % p;
		sum[o] = (sum[o] + d * (R - L + 1)) % p;
		return;
	}

	maintain(o, L, R);
	int mid = (L + R) / 2;
	u_add(2 * o, L, mid, d);
	u_add(2 * o + 1, mid + 1, R, d);
	sum[o] = (sum[o * 2] + sum[o * 2 + 1]) % p;
	return;



}

void u_mul(int o, int L, int R, int m)
{
	if (R<ql || L>qr)return;
	if (ql <= L && R <= qr)
	{
		sum[o] = (sum[o] * m) % p;
		addv[o] = (addv[o] * m) % p;
		mulv[o] = (mulv[o] * m) % p;
		return;
	}
	maintain(o, L, R);
	int mid = (L + R) / 2;
	u_mul(2 * o, L, mid, m);
	u_mul(2 * o + 1, mid + 1, R, m);
	sum[o] = (sum[o * 2] + sum[o * 2 + 1]) % p;
	return;



}


ll query(int o, int L, int R)//intial d=0,m=1;
{
	if (R<ql || L>qr)return 0;
	if (ql <= L && R <= qr)
		return sum[o];

	ll s1 = 0, s2 = 0;
	maintain(o, L, R);
	int mid = (L + R) / 2;
	s1 = query(2 * o, L, mid);
	s2 = query(2 * o + 1, mid + 1, R);
	return (s1 + s2) % p;
}

int main()
{
	memset(mulv, 1, sizeof(mulv));
	int n, m;
	cin >> n >> m >> p;
	for (int i = 1; i <= n; i++)
		a[i] = read();
	cons(1, 1, n);
	for (int i = 1; i <= m; i++)
	{
		ll g = 0;
		g = read();
		ql = read();
		qr = read();
		if (g == 1)
		{
			int k = read();
			u_mul(1, 1, n, k);
			continue;
		}
		if (g == 2)
		{
			int k = read();
			u_add(1, 1, n, k);
			continue;
		}
		if (g == 3)
		{
			ll s = query(1, 1, n);
			printf("%d\n", s);
			continue;
		}
	}


	return 0;
}


posted @ 2019-11-08 12:47  miyasaka  阅读(130)  评论(0)    收藏  举报