• bzoj1798 维护序列


    Description

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

    Input

    第一行两个整数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)。 同一行相邻两数之间用一个空格隔开,每行开头和末尾没有多余空格。

    Output

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

    Sample Input

    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

    Sample Output

    2
    35
    8

    HINT

    【样例说明】

    初始时数列为(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

     
    线段树乘法模板
    乘法的难点在于考虑先加再乘还是先乘再加

    当lazytage下标传递的时候,我们需要考虑,是先加再乘还是先乘再加。我们只需要对lazytage做这样一个处理。

    lazytage分为两种,分别是加法的plz和乘法的mlz。

    mlz很简单处理,pushdown时直接*父亲的就可以了,那么加法呢?

    我们需要把原先的plz*父亲的mlz再加上父亲的plz.

    #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 INF 10000009
    #define MOD 10000007
    #define LL long long
    #define in(a) a=read()
    #define REP(i,k,n) for(long long i=k;i<=n;i++)
    #define DREP(i,k,n) for(long long i=k;i>=n;i--)
    #define cl(a) memset(a,0,sizeof(a))
    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;
    }
    inline void out(long long x){
        if(x<0) putchar('-'),x=-x;
        if(x>9) out(x/10);
        putchar(x%10+'0');
    }
    long long n,m,p;
    long long input[MAXN];
    struct node{
        long long l,r;
        long long 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;
        if(l==r){
            tree[i].sum=input[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;
        tree[i<<1|1].sum=(tree[i<<1|1].sum*k1+k2*(tree[i<<1|1].r-tree[i<<1|1].l+1))%p;
        tree[i<<1].mlz=(tree[i<<1].mlz*k1)%p;
        tree[i<<1|1].mlz=(tree[i<<1|1].mlz*k1)%p;
        tree[i<<1].plz=(tree[i<<1].plz*k1+k2)%p;
        tree[i<<1|1].plz=(tree[i<<1|1].plz*k1+k2)%p;
        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].r<l || tree[i].l>r)  return ;
        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;
            tree[i].plz=(tree[i].plz*k)%p;
            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;
        return ;
    }
    inline void add(long long i,long long l,long long r,long long k){
        if(tree[i].r<l || tree[i].l>r)  return ;
        if(tree[i].l>=l && tree[i].r<=r){
            tree[i].sum+=((tree[i].r-tree[i].l+1)*k)%p;
            tree[i].plz=(tree[i].plz+k)%p;
            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;
        return ;
    }
    inline long long 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)%p;
        if(tree[i<<1|1].l<=r)  sum+=search(i<<1|1,l,r)%p;
        return sum%p;
    }
    int main(){
        in(n);in(p);
        REP(i,1,n)  in(input[i]);
        build(1,1,n); 
        in(m);
        REP(i,1,m){
            long long fl,a,b,c;
            in(fl);
            if(fl==1){
                in(a);in(b);in(c);
                c%=p;
                mul(1,a,b,c);
            }
            if(fl==2){
                in(a);in(b);in(c);
                c%=p;
                add(1,a,b,c);
            }
            if(fl==3){
                in(a);in(b);
                printf("%lld
    ",search(1,a,b));
            }
        }
        return 0;
    }
    /*
    5 4 1000
    1 2 3 4 5
    3 1 5
    2 1 5 1
    1 1 5 2
    
    3 1 5
    */ 
  • 相关阅读:
    UVa 1592 Database(巧用map)
    TZOJ 4746 Xiangqi(模拟棋盘数组)
    TZOJ 1545 Hurdles of 110m(01背包dp)
    TZOJ 2754 Watering Hole(最小生成树Kruskal)
    TZOJ 1242 求出前m大的数(预处理)
    TZOJ 5280 搜索引擎(模拟字符串)
    TZOJ 4865 统计单词数(模拟字符串)
    TZOJ 5279 马拉松比赛(广搜)
    [luogu4735]最大异或和
    小奇回地球
  • 原文地址:https://www.cnblogs.com/jason2003/p/9708838.html
Copyright © 2020-2023  润新知