zoukankan      html  css  js  c++  java
  • bzoj1798维护序列

    试题描述
    老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成。
    有长为 N 的数列,不妨设为 a1,a2,⋯,an。有如下三种操作:
    ①把数列中的一段数全部乘一个值;

    ②把数列中的一段数全部加一个值;

    ③询问数列中的一段数的和,由于结果可能很大,你只需输出这个数模 P 的值。

    输入
    第一行两个整数 N 和 P(1≤P≤1000000000)。第二行含有 N 个非负整数,从左到右依次为 a1,a2,⋯,aN,(0≤ai≤1000000000,1≤i≤N)。第三行有一个整数 M,表示操作总数。从第四行开始每行描述一个操作,输入的操作有以下三种形式:
    操作1:“1 t g c”(不含双引号)。表示把所有满足 t≤i≤gt 的 ai 改为ai*c(1≤t≤gN,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,按照它在输入中出现的顺序,依次输出一行一个整数表示询问结果。
    输入示例
    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
    输出示例
    2
    35
    8

    线段树还是板子,维护的时候一定要多注意取模

    然后要注意,写pushdown的时候一定要特判,否则会T

    下面给出出代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<cmath>
    using namespace std;
    inline long long rd(){
        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<<3)+(x<<1)+ch-'0';
        return x*f;
    }
    inline void write(long long x){
        if(x<0) putchar('-'),x=-x;
        if(x>9) write(x/10);
        putchar(x%10+'0');
        return ;
    }
    struct node{
        long long l,r;
        long long sum;
        long long f1,f2;
    }tree[4000006];
    long long n,mod,m;
    inline void build(long long i,long long x,long long y){
        tree[i].l=x,tree[i].r=y;
        tree[i].f2=1;
        if(x==y){
            tree[i].sum=rd();
            return ;
        }
        long long mid=(x+y)>>1;
        build(i<<1,x,mid);
        build(i<<1|1,mid+1,y);
        tree[i].sum=tree[i<<1].sum+tree[i<<1|1].sum;
        return ;
    }
    inline void pushdown(long long x){
        long long h1=tree[x].f1%mod,h2=tree[x].f2%mod;
        if(!h1&&h2==1) return ;
        tree[x<<1].sum=tree[x<<1].sum*h2+(tree[x<<1].r-tree[x<<1].l+1)*h1,tree[x<<1].sum%=mod;
        tree[x<<1|1].sum=tree[x<<1|1].sum*h2+(tree[x<<1|1].r-tree[x<<1|1].l+1)*h1,tree[x<<1|1].sum%=mod;
        tree[x<<1].f2*=h2,tree[x<<1|1].f2*=h2;
        tree[x<<1].f2%=mod,tree[x<<1|1].f2%=mod;
        tree[x<<1].f1*=h2,tree[x<<1].f1+=h1,tree[x<<1].f1%=mod;
        tree[x<<1|1].f1*=h2,tree[x<<1|1].f1+=h1,tree[x<<1|1].f1%=mod;
        tree[x].f1=0,tree[x].f2=1;
        return ;
    }
    inline void add(long long i,long long x,long long y,long long z){
        if(tree[i].l>=x&&tree[i].r<=y){
            tree[i].f1+=z,tree[i].f1%=mod;
            tree[i].sum+=(tree[i].r-tree[i].l+1)*z,tree[i].sum%=mod;
            return ;
        }
        pushdown(i);
        if(tree[i<<1].r>=x) add(i<<1,x,y,z);
        if(tree[i<<1|1].l<=y) add(i<<1|1,x,y,z);
        tree[i].sum=tree[i<<1].sum+tree[i<<1|1].sum,tree[i].sum%=mod;
        return ;
    }
    inline void mul(long long i,long long x,long long y,long long z){
        if(tree[i].l>=x&&tree[i].r<=y){
            tree[i].f2*=z;tree[i].f2%=mod;
            tree[i].f1*=z;tree[i].f1%=mod;
            tree[i].sum*=z;tree[i].sum%=mod;
            return ;
        }
        pushdown(i);
        if(tree[i<<1].r>=x) mul(i<<1,x,y,z);
        if(tree[i<<1|1].l<=y) mul(i<<1|1,x,y,z);
        tree[i].sum=tree[i<<1].sum+tree[i<<1|1].sum,tree[i].sum%=mod;
        return ;
    }
    inline long long solve(long long i,long long x,long long y){
        if(tree[i].l>=x&&tree[i].r<=y) return tree[i].sum%mod;
        pushdown(i);
        long long num=0;
        if(tree[i<<1].r>=x) num+=solve(i<<1,x,y),num%=mod;
        if(tree[i<<1|1].l<=y) num+=solve(i<<1|1,x,y),num%=mod;
        return num;
    }
    int main(){
        n=rd(),mod=rd();
        build(1,1,n);
        m=rd();
        while(m--){
            long long f=rd();
            if(f==1){
                long long x=rd(),y=rd(),z=rd();
                mul(1,x,y,z);
            }
            if(f==2){
                long long x=rd(),y=rd(),z=rd();
                add(1,x,y,z);
            }
            if(f==3){
                long long x=rd(),y=rd();
                write(solve(1,x,y)%mod),puts("");
            }
        }
        return 0;
    }
    蒟蒻总是更懂你✿✿ヽ(°▽°)ノ✿
  • 相关阅读:
    《3D Math Primer for Graphics and Game Development》读书笔记1
    OpenGL学习资料汇总
    [Unity3D]做个小Demo学习Input.touches
    [Unity3D]再次点击以退出程序
    图文详解Unity3D中Material的Tiling和Offset是怎么回事
    自制Unity小游戏TankHero-2D(5)声音+爆炸+场景切换+武器弹药
    自制Unity小游戏TankHero-2D(4)关卡+小地图图标+碰撞条件分析
    Unity3D核心类型一览
    自制Unity小游戏TankHero-2D(3)开始玩起来
    自制Unity小游戏TankHero-2D(2)制作敌方坦克
  • 原文地址:https://www.cnblogs.com/WWHHTT/p/9803689.html
Copyright © 2011-2022 走看看