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;
}

 

posted @ 2018-10-17 13:54  Bruce--Wang  阅读(135)  评论(0编辑  收藏  举报