• 洛谷 P2023 [AHOI2009]维护序列


    题目描述

    老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成。 有长为N的数列,不妨设为a1,a2,…,aN 。有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2)把数列中的一段数全部加一个值; (3)询问数列中的一段数的和,由于答案可能很大,你只需输出这个数模P的值。

    输入输出格式

    输入格式:

     

    第一行两个整数N和P(1≤P≤1000000000)。 第二行含有N个非负整数,从左到右依次为a1,a2,…,aN, (0≤ai≤1000000000,1≤i≤N)。 第三行有一个整数M,表示操作总数。 从第四行开始每行描述一个操作,输入的操作有以下三种形式: 操作1:“1 t g c”(不含双引号)。表示把所有满足t≤i≤g的ai改为ai×c (1≤t≤g≤N,0≤c≤1000000000)。 操作2:“2 t g c”(不含双引号)。表示把所有满足t≤i≤g的ai改为ai+c (1≤t≤g≤N,0≤c≤1000000000)。 操作3:“3 t g”(不含双引号)。询问所有满足t≤i≤g的ai的和模P的值 (1≤t≤g≤N)。 同一行相邻两数之间用一个空格隔开,每行开头和末尾没有多余空格。

     

    输出格式:

     

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

     

    输入输出样例

    输入样例#1: 复制
    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
    输出样例#1: 复制
    2
    35
    8
    

    说明

    【样例说明】

    初始时数列为(1,2,3,4,5,6,7)。

    经过第1次操作后,数列为(1,10,15,20,25,6,7)。

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

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

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

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

    测试数据规模如下表所示

    数据编号 1 2 3 4 5 6 7 8 9 10

    N= 10 1000 1000 10000 60000 70000 80000 90000 100000 100000

    M= 10 1000 1000 10000 60000 70000 80000 90000 100000 100000

    Source: Ahoi 2009

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define MAXN 100001
    using namespace std;
    struct nond{
        long long l,r,sum;
        long long flag1,falg2;
    }tree[MAXN*4];
    long long n,m,p;
    void up(long long now){
        tree[now].sum=(tree[now*2].sum+tree[now*2+1].sum)%p;
    }
    void build(long long now,long long l,long long r){
        tree[now].l=l;tree[now].r=r;
        tree[now].flag1=1;tree[now].falg2=0;
        if(tree[now].l==tree[now].r){
            scanf("%d",&tree[now].sum);
            return ;
        }
        long long mid=(tree[now].l+tree[now].r)/2;
        build(now*2,l,mid);
        build(now*2+1,mid+1,r);
        up(now);
    }
    void down(long long now){
        if(tree[now].flag1!=1){
            tree[now*2].flag1=tree[now*2].flag1*tree[now].flag1%p;
            tree[now*2].falg2=tree[now*2].falg2*tree[now].flag1%p;
            tree[now*2].sum=tree[now*2].sum*tree[now].flag1%p;
            tree[now*2+1].flag1=tree[now*2+1].flag1*tree[now].flag1%p;
            tree[now*2+1].falg2=tree[now*2+1].falg2*tree[now].flag1%p;
            tree[now*2+1].sum=tree[now*2+1].sum*tree[now].flag1%p;
            tree[now].flag1=1;
        }
        if(tree[now].falg2){
            tree[now*2].falg2=(tree[now*2].falg2+tree[now].falg2)%p;
            tree[now*2+1].falg2=(tree[now*2+1].falg2+tree[now].falg2)%p;
            tree[now*2].sum=(tree[now*2].sum+(tree[now*2].r-tree[now*2].l+1)*tree[now].falg2%p)%p;
            tree[now*2+1].sum=(tree[now*2+1].sum+(tree[now*2+1].r-tree[now*2+1].l+1)*tree[now].falg2%p)%p;
            tree[now].falg2=0;
        }
    }
    void changechen(long long now,long long l,long long r,long long k){
        if(tree[now].l==l&&tree[now].r==r){
            tree[now].sum=tree[now].sum*k%p;
            tree[now].flag1=tree[now].flag1*k%p;
            tree[now].falg2=tree[now].falg2*k%p;
            return ;    
        }
        if(tree[now].flag1!=1||tree[now].falg2)    down(now);
        long long mid=(tree[now].l+tree[now].r)/2;
        if(r<=mid)    changechen(now*2,l,r,k);
        else if(l>mid)    changechen(now*2+1,l,r,k);
        else{
            changechen(now*2,l,mid,k);
            changechen(now*2+1,mid+1,r,k);
        }
        up(now);
    }
    void changeadd(long long now,long long l,long long r,long long k){
        if(tree[now].l==l&&tree[now].r==r){
            tree[now].sum=(tree[now].sum+(tree[now].r-tree[now].l+1)*k%p)%p;
            tree[now].falg2=(tree[now].falg2+k)%p;
            return ;    
        }
        if(tree[now].flag1!=1||tree[now].falg2)    down(now);
        long long mid=(tree[now].l+tree[now].r)/2;
        if(r<=mid)    changeadd(now*2,l,r,k);
        else if(l>mid)    changeadd(now*2+1,l,r,k);
        else{
            changeadd(now*2,l,mid,k);
            changeadd(now*2+1,mid+1,r,k);
        }
        up(now);
    }
    long long query(long long now,long long l,long long r){
        if(tree[now].l==l&&tree[now].r==r)
            return tree[now].sum%p;
        if(tree[now].flag1!=1||tree[now].falg2)    down(now);
        long long mid=(tree[now].l+tree[now].r)/2;
        if(r<=mid)    return query(now*2,l,r);
        else if(l>mid)    return query(now*2+1,l,r);
        else    return (query(now*2,l,mid)+query(now*2+1,mid+1,r))%p;
    }
    int main(){
        scanf("%lld%lld",&n,&p);
        build(1,1,n);scanf("%lld",&m);
        for(long long i=1;i<=m;i++){
            long long opt,x,y,k;
            scanf("%lld%lld%lld",&opt,&x,&y);
            if(opt==1){
                scanf("%lld",&k);
                changechen(1,x,y,k);
            }
            else if(opt==2){
                scanf("%lld",&k);
                changeadd(1,x,y,k);
            }
            else if(opt==3)    printf("%lld
    ",query(1,x,y)%p);
        }
    }
    细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。 雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。
  • 相关阅读:
    Oracle SQL语句大全—查看表空间
    Class to disable copy and assign constructor
    在moss上自己总结了点小经验。。高手可以飘过 转贴
    在MOSS中直接嵌入ASP.NET Page zt
    Project Web Access 2007自定义FORM验证登录实现 zt
    SharePoint Portal Server 2003 中的单一登录 zt
    vs2008 开发 MOSS 顺序工作流
    VS2008开发MOSS工作流几个需要注意的地方
    向MOSS页面中添加服务器端代码的另外一种方式 zt
    状态机工作流的 SpecialPermissions
  • 原文地址:https://www.cnblogs.com/cangT-Tlan/p/8687440.html
Copyright © 2020-2023  润新知