专题二树形结构 M - 维护序列

  1. 题目
    题目描述

    原题来自:AHOI 2009

    老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成。

    有长为 的数列,不妨设为 a1,a2,⋯ ,ana_1,a_2,\cdots ,a_n。有如下三种操作形式:

    • 把数列中的一段数全部乘一个值;
    • 把数列中的一段数全部加一个值;
    • 询问数列中的一段数的和,由于答案可能很大,你只需输出这个数模 PP 的值。
    输入格式

    第一行两个整数

    第二行含有 个非负整数,从左到右依次为 a1,a2,⋯ ,ana_1,a_2,\cdots ,a_n

    第三行有一个整数 ,表示操作总数;

    从第四行开始每行描述一个操作,输入的操作有以下三种形式:

    • 操作 1 t g c,表示把所有满足 t≤i≤gt\le i\le gaia_i 改为 ai×ca_i\times c
    • 操作 2 t g c,表示把所有满足 t≤i≤gt\le i\le gaia_i 改为 ai+ca_i+c
    • 操作 3 t g,询问所有满足 t≤i≤gt\le i\le gaia_i 的和模 的值。

    同一行相邻两数之间用一个空格隔开,每行开头和末尾没有多余空格。

    输出格式

    对每个操作 ,按照它在输入中出现的顺序,依次输出一行一个整数表示询问结果。

    样例
    Inputcopy Outputcopy
    7 43
    1 2 3 4 5 6 7
    5
    1 2 5 5
    3 2 4
    2 3 7 9
    3 1 3
    3 4 7
    2
    35
    8

    初始时数列为 {1,2,3,4,5,6,7}{1,2,3,4,5,6,7}

    经过第 1 次操作后,数列为 {1,10,15,20,25,6,7}{1,10,15,20,25,6,7}

    对第 2 次操作,和为 10+15+20=4510+15+20=45,模 的结果是 22

    经过第 3 次操作后,数列为 {1,10,24,29,34,15,16}{1,10,24,29,34,15,16}

    对第 4 次操作,和为 1+10+24=351+10+24=35,模 的结果是 3535

    对第 5 次操作,和为 29+34+15+16=9429+34+15+16=94,模 的结果是 88

    数据范围与提示

    对于全部测试数据,1≤t≤g≤n,0≤c,ai≤109,1≤P≤109+71\le t\le g\le n,0\le c,a_i\le 10^9,1\le P\le 10^9+7

  2. 思路
    对数据进行加法、乘法、模的操作,加法乘法各需要一个懒惰标记,乘法的懒惰标记要初始化为1
    注意乘法操作的时候节点值和所有懒惰标记都要一起乘,数据的每一步加减乘除之后都要模一下
  3. 代码
    #include<cstdio>
    #include<iostream>
    #include<string>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    #define clear(a,x) memset(a,x,sizeof(a))
    #define ll long long
    
    ll d[1000000],la[1000000],lm[1000000],a[1000005];//区间值,加法乘法懒惰标记,原始值
    ll n,q,mod;
    
    void pd(ll i, ll s, ll t) {
    	ll l = (i << 1), r = (i << 1) + 1, mid = s + ((t - s) >> 1);
    	if (lm[i] != 1) {
    	    lm[l] *= lm[i];lm[l] %= mod;
    	    lm[r] *= lm[i];lm[r] %= mod;
    	    la[l] *= lm[i];la[l] %= mod;
    	    la[r] *= lm[i];la[r] %= mod;
    	    d[l] *= lm[i];d[l] %= mod;
    	    d[r] *= lm[i];d[r] %= mod;
    	    lm[i] = 1;
    	}
    	if (la[i]) {
    	    d[l] += la[i] * (mid - s + 1);d[l] %= mod;
    	    d[r] += la[i] * (t - mid);d[r] %= mod;
    	    la[l] += la[i];la[l] %= mod;
    	    la[r] += la[i];la[r] %= mod;
    	    la[i] = 0;
    	}
    	return;
    }
    
    void build(ll s, ll t, ll p) {
    
    	if (s == t) {
    	    d[p] = a[s];
    		lm[p] = 1;
    	    return;
    	}
    
    	ll m = s + ((t - s) >> 1);
    	build(s, m, p * 2), build(m + 1, t, p * 2 + 1);
    	d[p] = d[p * 2] + d[(p * 2) + 1];
    	lm[p] = 1;
    }
    
    void update(ll l, ll r, ll c, ll s, ll t, ll p) {
    
    	if (l <= s && t <= r) {
    		d[p] += (t - s + 1) * c, la[p] += c;
    		d[p] %= mod, la[p] %= mod;
    	    return;
    	}
    
    	ll m = s + ((t - s) >> 1);
    	pd(p,s,t);
    	if (l <= m) update(l, r, c, s, m, p * 2);
    	if (r > m) update(l, r, c, m + 1, t, p * 2 + 1);
    	d[p] = (d[p * 2] + d[p * 2 + 1]) % mod;
    }
    
    void updatem(ll l, ll r, ll c, ll s, ll t, ll p) {
    
    	if (l <= s && t <= r) {
    		d[p] *= c, lm[p] *= c, la[p] *= c;
    		d[p] %= mod, lm[p] %= mod, la[p] %= mod;
    	    return;
    	}
    
    	ll m = s + ((t - s) >> 1);
    	pd(p,s,t);
    	if (l <= m) updatem(l, r, c, s, m, p * 2);
    	if (r > m) updatem(l, r, c, m + 1, t, p * 2 + 1);
    	d[p] = (d[p * 2] + d[p * 2 + 1]) % mod;
    }
    
    ll getsum(ll l, ll r, ll s, ll t, ll p) {
    
    	if (l <= s && t <= r) return d[p];
    
    	ll m = s + ((t - s) >> 1);
    	pd(p,s,t);
    	ll sum = 0;
    	if (l <= m) sum += getsum(l, r, s, m, p * 2);
    	sum %= mod;
    	if (r > m) sum += getsum(l, r, m + 1, t, p * 2 + 1);
    	return sum % mod;
    }
    
    int main()
    {
    	scanf("%lld%lld",&n,&mod);
    	clear(d,0);
    	clear(la,0);
    	for(int i=1;i<=n;i++){
    		scanf("%lld",&a[i]);
    	}
    	build(1,n,1);
    	scanf("%lld",&q);
    	ll op,x,y,z;
    	while (q--) {
    		cin >> op >> x >> y;
    	if (op == 3)
    		cout << getsum(x, y, 1, n, 1) <<endl;
    	else if (op == 2)
    		cin >> z, update(x, y, z, 1, n, 1);
    	else
    		cin >> z, updatem(x, y, z, 1, n, 1);
    	}
    }
posted @ 2022-02-06 23:38  Benincasa  阅读(54)  评论(0)    收藏  举报