##Segment Tree Template

馅断术模板啦~

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

  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;
}

猜你喜欢

转载自www.cnblogs.com/kion/p/11819405.html