• 【模板】线段树2


    题意简述

    已知一个数列,你需要进行下面三种操作:
    1.将某区间每一个数乘上x
    2.将某区间每一个数加上x
    3.求出某区间每一个数的和

    代码

    #include <cstdio>
    using namespace std;
    typedef long long ll;
    ll n, m, opt, x, y, k, mod;
    ll a[400010], la1[400010], la2[400010];
    void push_up(ll x)
    {
    	a[x] = (a[x << 1] + a[x << 1 | 1]) % mod;
    }
    void push_down(ll x, ll len)
    {
    	if (la2[x] != 1)
    	{
    		(a[x << 1] *= la2[x]) %= mod;
    		(a[x << 1 | 1] *= la2[x]) %= mod;
    		(la1[x << 1] *= la2[x]) %= mod;
    		(la1[x << 1 | 1] *= la2[x]) %= mod;
    		(la2[x << 1] *= la2[x]) %= mod;
    		(la2[x << 1 | 1] *= la2[x]) %= mod;
    		la2[x] = 1;
    	}
    	if (la1[x])
    	{
    		(a[x << 1] += la1[x] * (len - (len >> 1)) % mod) %= mod;
    		(a[x << 1 | 1] += la1[x] * (len >> 1) % mod) %= mod;
    		(la1[x << 1] += la1[x]) %= mod;
    		(la1[x << 1 | 1] += la1[x]) %= mod;
    		la1[x] = 0;
    	}
    }
    void build(ll x, ll l, ll r)
    {
    	la2[x] = 1;
    	if (l == r)
    	{
    		scanf("%lld", &a[x]);
    		return;
    	}
    	ll mid = l + r >> 1;
    	build(x << 1, l, mid);
    	build(x << 1 | 1, mid + 1, r);
    	push_up(x);
    }
    void multiply(ll x, ll l, ll r, ll l1, ll r1)
    {
    	if(l1 <= l && r <= r1)
    	{
    		(a[x] *= k) %= mod;
    		(la1[x] *= k) %= mod;
    		(la2[x] *= k) %= mod;
    		return;
    	}
    	push_down(x, r - l + 1);
    	ll mid = l + r >> 1;
    	if (l1 <= mid) multiply(x << 1, l, mid, l1, r1);
    	if (r1 >  mid) multiply(x << 1 | 1, mid + 1, r, l1, r1);
    	push_up(x);
    }
    void add(ll x, ll l, ll r, ll l1, ll r1)
    {
    	if (l1 <= l && r <= r1)
    	{
    		(a[x] += (r - l + 1) * k % mod) %= mod;
    		(la1[x] += k) %= mod;
    		return;
    	}
    	push_down(x, r - l + 1);
    	ll mid = l + r >> 1;
    	if (l1 <= mid) add(x << 1, l, mid, l1, r1);
    	if (r1 >  mid) add(x << 1 | 1, mid + 1, r, l1, r1);
    	push_up(x);
    }
    ll query(ll x, ll l, ll r, ll l1, ll r1, ll ans = 0)
    {
    	if (l1 <= l && r <= r1)	return a[x];
    	push_down(x, r - l + 1);
    	ll mid = l + r >> 1;
    	if (l1 <= mid) (ans += query(x << 1, l, mid, l1, r1)) %= mod;
    	if (r1 >  mid) (ans += query(x << 1 | 1, mid + 1, r, l1, r1)) %= mod;
    	return ans;
    }
    int main()
    {
    	scanf("%lld%lld%lld", &n, &m, &mod);
    	build(1, 1, n);
    	for (register ll i = 1; i <= m; ++i)
    	{
    		scanf("%lld", &opt);
    		if (opt == 1)
    		{
    			scanf("%lld%lld%lld", &x, &y, &k);
    			multiply(1, 1, n, x, y);
    		}
    		if (opt == 2)
    		{
    			scanf("%lld%lld%lld", &x, &y, &k);
    			add(1, 1, n, x, y);
    		}
    		if (opt == 3)
    		{
    			scanf("%lld%lld", &x, &y);
    			printf("%lld
    ", query(1, 1, n, x, y));
    		}
    	}
    }
    
  • 相关阅读:
    VB中Null、Empty、Nothing及vbNullString的区别
    hs_err_pidXXX.log 解读
    测试Windows Live Writer——开博
    BCPC2021预赛
    软件设计模式之策略模式(Strategy) 壹
    留言板 壹
    友链 壹
    正则表达式练习 壹
    SpringBoot+Mybatis+自定义注解+Atomikos+实现多源数据库切换和分布式事务
    Dependency failed for File System Check on /dev/vdb1 服务器配置升级
  • 原文地址:https://www.cnblogs.com/xuyixuan/p/9470594.html
Copyright © 2020-2023  润新知