• 【模板】线段树 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)

    #include<iostream>
    #include<cstdio>
    using namespace std;
    
    int p;
    
    long long a[100007];
    
    struct node{
        long long v,mul,add;
    }st[400007];
    
    void bt(int root,int l,int r){
        st[root].mul=1;
        st[root].add=0;
        if(l==r){
            st[root].v=a[l];
        }
        else{
            int m=(l+r)/2;
            bt(root*2,l,m);
            bt(root*2+1,m+1,r);
            st[root].v=st[root*2].v+st[root*2+1].v;
        }
        st[root].v%=p;
        return;
    }
    
    void pushdown(int root,int l,int r){
        int m=(l+r)/2;
        st[root*2].v=(st[root*2].v*st[root].mul+st[root].add*(m-l+1))%p;
        st[root*2+1].v=(st[root*2+1].v*st[root].mul+st[root].add*(r-m))%p;
        st[root*2].mul=(st[root*2].mul*st[root].mul)%p;
        st[root*2+1].mul=(st[root*2+1].mul*st[root].mul)%p;
        st[root*2].add=(st[root*2].add*st[root].mul+st[root].add)%p;
        st[root*2+1].add=(st[root*2+1].add*st[root].mul+st[root].add)%p;
        st[root].mul=1;
        st[root].add=0;
        return;
    }
    
    void ud1(int root, int stdl, int stdr, int l, int r, long long k){
        if(r<stdl||stdr<l){
            return ;
        }
        if(l<=stdl && stdr<=r){
            st[root].v=(st[root].v*k)%p;
            st[root].mul=(st[root].mul*k)%p;
            st[root].add=(st[root].add*k)%p;
            return ;
        }
        pushdown(root, stdl, stdr);
        int m=(stdl+stdr)/2;
        ud1(root*2, stdl, m, l, r, k);
        ud1(root*2+1, m+1, stdr, l, r, k);
        st[root].v=(st[root*2].v+st[root*2+1].v)%p;
        return;
    }
    void ud2(int root, int stdl, int stdr, int l, int r, long long k){
        if(r<stdl||stdr<l){
            return;
        }
        if(l<=stdl && stdr<=r){
            st[root].add=(st[root].add+k)%p;
            st[root].v=(st[root].v+k*(stdr-stdl+1))%p;
            return;
        }
        pushdown(root, stdl, stdr);
        int m=(stdl+stdr)/2;
        ud2(root*2, stdl, m, l, r, k);
        ud2(root*2+1, m+1, stdr, l, r, k);
        st[root].v=(st[root*2].v+st[root*2+1].v)%p;
        return;
    }
    
    long long query(int root,int stdl,int stdr,int l,int r){
        if(r<stdl||stdr<l){
            return 0;
        }
        if(l<=stdl && stdr<=r){
            return st[root].v;
        }
        pushdown(root,stdl,stdr);
        int m=(stdl+stdr)/2;
        return (query(root*2, stdl, m, l, r)+query(root*2+1, m+1, stdr, l, r))%p;
    }
    
    int main(){ 
        int n, m;
        scanf("%d%d%d", &n, &m, &p);
        for(int i=1; i<=n; i++){
            scanf("%lld", &a[i]);
        }
        bt(1, 1, n);
        while(m--){
            int chk;
            scanf("%d", &chk);
            int x, y;
            long long k;
            if(chk==1){
                scanf("%d%d%lld", &x, &y, &k);
                ud1(1, 1, n, x, y, k);
            }
            else if(chk==2){
                scanf("%d%d%lld", &x, &y, &k);
                ud2(1, 1, n, x, y, k);
            }
            else{
                scanf("%d%d", &x, &y);
                printf("%lld
    ", query(1, 1, n, x, y));
            }
        }
        return 0;
    }
  • 相关阅读:
    整数m去掉n位后剩下最大(小)值
    蛇形矩阵(二)
    Kibana源码启动报错记录--ENOSPC
    Kibana问题记录:yarn test 运行报错 error Trailing spaces not allowed no-trailing-spaces
    Vim 编辑器中全选操作
    Ubuntu系统中连接TFS的Git地址注意事项
    Ubuntu系统升级遇到问题记录
    Kibana6.2.x 插件理解
    Kibana问题搜集---下载源码,执行npm install 报错
    Kibana6.2.2源码入口
  • 原文地址:https://www.cnblogs.com/hrj1/p/11206035.html
Copyright © 2020-2023  润新知