• 线段树【加强】


    题目描述

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

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

     

    输入输出样例

    输入
    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
    输出
    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)


    终于调好了线段树(累……

    记住:

    不开longlong见祖宗,十年oi一场空

    code

    #include<stdio.h> 
    #include<algorithm>
    #define ls x<<1
    #define rs x<<1|1 
    using namespace std;
    const int mxn=110000;
    int n,m,P,tree[mxn<<2],add[mxn<<2],mul[mxn<<2];
    int ql,qr,num,cas;
    
    void build(int x,int l,int r) 
    {
        mul[x]=1;
        if(l==r) scanf("%d",&tree[x]);
        else {
            int mid=(l+r)>>1;
            build(ls,l,mid);
            build(rs,mid+1,r);
            tree[x]=tree[ls]+tree[rs];
        }
    }
    
    void pd(int x,int l,int r,int mid) {
        if(mul[x]!=1) {
            mul[ls]=mul[ls]*mul[x]%P;
            add[ls]=add[ls]*mul[x]%P;
            tree[ls]=tree[ls]*mul[x]%P;
            mul[rs]=mul[rs]*mul[x]%P;
            add[rs]=add[rs]*mul[x]%P;
            tree[rs]=tree[rs]*mul[x]%P;
            mul[x]=1;
        }
        if(add[x]) {
            add[ls]=(add[ls]+add[x])%P;
            tree[ls]=(tree[ls]+(mid-l+1)*add[x])%P;
            add[rs]=(add[rs]+add[x])%P;
            tree[rs]=(tree[rs]+(r-mid)*add[x])%P;
            add[x]=0;
        }
    } 
     
    void sol(int x,int l,int r) 
    {
        if(ql<=l&&qr>=r) 
        {
            if(cas==1) { //
                mul[x]=mul[x]*num%P;
                add[x]=add[x]*num%P;
                tree[x]=tree[x]*num%P;
            }
            else { //
                add[x]=(add[x]+num)%P;
                tree[x]=(tree[x]+num*(r-l+1))%P;
            }
            return ;
        }
        int mid=(l+r)>>1;
        pd(x,l,r,mid);
        if(ql<=mid) sol(ls,l,mid);
        if(qr>mid) sol(rs,mid+1,r);
        tree[x]=tree[ls]+tree[rs];
    }
    
    int ask(int x,int l,int r) 
    {
        if(ql<=l && qr>=r) return tree[x]; 
        int mid=(l+r)>>1,re=0;
        pd(x,l,r,mid);
        if(ql<=mid) re=(re+ask(ls,l,mid))%P;
        if(qr>mid) re=(re+ask(rs,mid+1,r))%P;
        return re;
    }
    int main() 
    {
        scanf("%d%d%d",&n,&m,&P);
        build(1,1,n);
        while(m--) 
        {
            scanf("%d%d%d",&cas,&ql,&qr);
            if(cas==3) printf("%d
    ",ask(1,1,n));
            else {
                scanf("%d",&num);
                sol(1,1,n);
            }
        }
        return 0;
    }
    /*
    8 10 571373
    5929 7152 8443 6028 8580 5449 8473 4237 
    2 4 8 4376
    1 2 8 9637
    2 2 6 7918
    2 5 8 5681
    3 2 8
    1 1 5 6482
    3 1 5
    1 5 8 8701
    2 5 8 7992
    2 5 8 7806
    
    478836
    562114
    */
  • 相关阅读:
    uboot的mtd功能支持
    ARM920T系统总线时序分析
    NorFlash
    编译u-boot命令和u-boot常用命令
    uboot启动linux的过程
    debug(fmt,args...)调试
    APCS
    You've got to find what you love
    debian , ubuntu 截取下拉菜单
    关于bash的shellshock漏洞
  • 原文地址:https://www.cnblogs.com/qseer/p/9833387.html
Copyright © 2020-2023  润新知