洛谷 P3373 【模板】线段树 2(线段树区间乘、加 区间查找)

题目描述

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

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的结果。

输入输出样例

输入 #1 复制
5 5 38
1 5 4 2 3
2 1 4 1
3 2 5
1 2 4 2
2 3 5 5
3 1 4
输出 #1 复制
17
2

说明/提示

时空限制:1000ms,128M

数据规模:

对于30%的数据:N<=8,M<=10

对于70%的数据:N<=1000,M<=10000

对于100%的数据:N<=100000,M<=100000

(数据已经过加强^_^)

样例说明:

故输出应为17、2(40 mod 38=2)

///
///                            _ooOoo_
///                           o8888888o
///                           88" . "88
///                           (| -_- |)
///                           O\  =  /O
///                        ____/`---'\____
///                      .'  \\|     |//  `.
///                     /  \\|||  :  |||//  \
///                    /  _||||| -:- |||||-  \
///                    |   | \\\  -  /// |   |
///                    | \_|  ''\---/''  |   |
///                    \  .-\__  `-`  ___/-. /
///                  ___`. .'  /--.--\  `. . __
///               ."" '<  `.___\_<|>_/___.'  >'"".
///              | | :  `- \`.;`\ _ /`;.`/ - ` : | |
///              \  \ `-.   \_ __\ /__ _/   .-` /  /
///         ======`-.____`-.___\_____/___.-`____.-'======
///                            `=---='
///        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
///                      Buddha Bless, No Bug !
///
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <queue>
#include <stack>
#include <vector>
using namespace std;
#define MAXN 100010
#define ll long long
#define in(a) a=read()
inline long long read()///读入数据
{
    long long x=0,f=1;
    char ch=getchar();
    for(; !isdigit(ch); ch=getchar())
        if(ch=='-')
            f=-1;
    for(; isdigit(ch); ch=getchar())
        x=x*10+ch-'0';
    return x*f;
}

ll n, m, p, a[MAXN];

struct node
{
    ll l, r, sum, mlz, plz;
} tree[4*MAXN];

inline void build(long long i,long long l,long long r)///建树
{
    tree[i].l=l;
    tree[i].r=r;
    tree[i].mlz=1;
    tree[i].plz = 0;
    if(l==r)
    {
        tree[i].sum=a[l]%p;
        return ;
    }
    long long mid=(l+r)>>1;
    build(i<<1,l,mid);///往左儿子那边的区间建树
    build(i<<1|1,mid+1,r);///往右儿子那边的区间建树
    tree[i].sum=(tree[i<<1].sum+tree[i<<1|1].sum)%p;///父节点的和等于左儿子的和加右儿子的和
    return ;
}

inline void pushdown(long long i)
{
    long long k1=tree[i].mlz,k2=tree[i].plz;
    tree[i<<1].sum=(tree[i<<1].sum*k1+k2*(tree[i<<1].r-tree[i<<1].l+1))%p;///(左儿子的值)等于(左儿子的值)*(父节点的mlz)+(父节点的plz)*(左儿子所控制的区间)
    tree[i<<1|1].sum=(tree[i<<1|1].sum*k1+k2*(tree[i<<1|1].r-tree[i<<1|1].l+1))%p;///(右儿子的值)等于(右儿子的值)*(父节点的mlz)+(父节点的plz)*(右儿子所控制的区间)
    tree[i<<1].mlz=(tree[i<<1].mlz*k1)%p;///把父节点的mlz传给左儿子
    tree[i<<1|1].mlz=(tree[i<<1|1].mlz*k1)%p;///把父节点的mlz传给右儿子
    tree[i<<1].plz=(tree[i<<1].plz*k1+k2)%p;///(左儿子的plz)等于(左儿子plz)*(父节点mlz)+(父节点plz),即为看这个点加了多少东西
    tree[i<<1|1].plz=(tree[i<<1|1].plz*k1+k2)%p;///(右儿子的plz)等于(右儿子plz)*(父节点mlz)+(父节点plz),即为看这个点加了多少东西
    tree[i].plz=0;
    tree[i].mlz=1;
    return ;
}

inline void mul(long long i,long long l,long long r,long long k)
{
    if(tree[i].l>=l && tree[i].r<=r)///如果所查找的区间在目的区间内
    {
        tree[i].sum=(tree[i].sum*k)%p;///返回这个值
        tree[i].mlz=(tree[i].mlz*k)%p;///mlz的懒惰标记
        tree[i].plz=(tree[i].plz*k)%p;///plz*k表示这个区间加了那么多东西(包括了之前加的部分)
        return ;
    }
    pushdown(i);
    if(tree[i<<1].r>=l)  mul(i<<1,l,r,k);///如果要查找的区间在左儿子部分,就搜索左儿子
    if(tree[i<<1|1].l<=r)  mul(i<<1|1,l,r,k);///如果要查找的区间在右儿子部分,就搜索右儿子
    tree[i].sum=(tree[i<<1].sum+tree[i<<1|1].sum)%p;///父节点sum等于两个儿子的sum
    return ;
}

inline void add(long long i,long long l,long long r,long long k)
{
    if(tree[i].l>=l && tree[i].r<=r)///如果所查找的区间在目的区间内
    {
        tree[i].sum+=((tree[i].r-tree[i].l+1)*k)%p;///(该区间的和)等于(该区间的和)+(该区间所控制的元素个数)*K
        tree[i].plz=(tree[i].plz+k)%p;///标记这个区间每个元素已经加了k
        return ;
    }
    pushdown(i);
    if(tree[i<<1].r>=l)  add(i<<1,l,r,k);///如果要查找的区间在左儿子部分,就搜索左儿子
    if(tree[i<<1|1].l<=r)  add(i<<1|1,l,r,k);///如果要查找的区间在右儿子部分,就搜索右儿子
    tree[i].sum=(tree[i<<1].sum+tree[i<<1|1].sum)%p;///父节点sum等于两个儿子的sum
    return ;
}

inline ll search(long long i,long long l,long long r)
{
    if(tree[i].r<l || tree[i].l>r) return 0;///如果这个区间不在要找的区间范围内
    if(tree[i].l>=l && tree[i].r<=r)///如果所查找的区间在目的区间内
    {
        return tree[i].sum;///直接返回这个区间的和
    }
    pushdown(i);
    long long sum=0;
    if(tree[i<<1].r>=l)  sum += search(i<<1,l,r);///如果要查找的区间在左儿子部分,就搜索左儿子
    if(tree[i<<1|1].l<=r)  sum += search(i<<1|1,l,r);///如果要查找的区间在右儿子部分,就搜索右儿子
    return sum %= p;
}

int main()
{
    in(n);
    in(m);
    in(p);
    for(int i = 1; i <= n; i++)
        in(a[i]);
    build(1,1,n);///建树

    for(int i = 1; i <= m; i++)
    {
        ll fl;
        in(fl);
        if(fl==1)
        {
            ll x, y, k;
            in(x);
            in(y);
            in(k);
            k%=p;
            mul(1, x, y, k);///
        }
        if(fl==2)
        {
            ll x, y, k;
            in(x);
            in(y);
            in(k);
            k%=p;
            add(1, x, y, k);///
        }
        if(fl==3)
        {
            ll x, y;
            in(x);
            in(y);
            printf("%lld\n", search(1,x,y));///区间查找
        }
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/RootVount/p/11293929.html

深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值