bzoj 1798: [Ahoi2009]Seq 维护序列seq (线段树)

来源:互联网 发布:手机识图软件 编辑:程序博客网 时间:2024/05/15 10:00

题目描述

传送门

题目大意:有长为N的数列,不妨设为a1,a2,…,aN 。有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2)把数列中的一段数全部加一个值; (3)询问数列中的一段数的和,由于答案可能很大,你只需输出这个数模P的值

题解

线段树维护加乘标记的裸题。。。

代码

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#define N 400003#define LL long long using namespace std;int n,m,a[N];LL tr[N],add[N],mul[N],p;void update(int x){    tr[x]=(tr[x<<1]+tr[x<<1|1])%p;}void build(int now,int l,int r){    mul[now]=1; add[now]=0;    if (l==r) {        tr[now]=a[l]; mul[now]=1;        return;    }    int mid=(l+r)/2;    build(now<<1,l,mid);    build(now<<1|1,mid+1,r);    update(now);}void pushdown(int now,int l,int r){    int mid=(l+r)/2;    if (mul[now]!=1) {        tr[now<<1]=tr[now<<1]*mul[now]%p;        tr[now<<1|1]=tr[now<<1|1]*mul[now]%p;        mul[now<<1]=mul[now<<1]*mul[now]%p;        mul[now<<1|1]=mul[now<<1|1]*mul[now]%p;        add[now<<1]=add[now<<1]*mul[now]%p;        add[now<<1|1]=add[now<<1|1]*mul[now]%p;        mul[now]=1;    }    if (add[now]) {        tr[now<<1]+=add[now]*(mid-l+1)%p;        if (tr[now]>=p) tr[now]-=p;        tr[now<<1|1]+=add[now]*(r-mid)%p;        if (tr[now]>=p) tr[now]-=p;        add[now<<1]+=add[now];        if (add[now]>=p) add[now]-=p;        add[now<<1|1]+=add[now];         if (add[now]>=p) add[now]-=p;        add[now]=0;    }}void qjmul(int now,int l,int r,int ll,int rr,LL val){    if (ll<=l&&r<=rr) {        tr[now]=tr[now]*val%p;        mul[now]=mul[now]*val%p;        add[now]=add[now]*val%p;        return;    }    int mid=(l+r)/2;    pushdown(now,l,r);    if (ll<=mid) qjmul(now<<1,l,mid,ll,rr,val);    if (rr>mid) qjmul(now<<1|1,mid+1,r,ll,rr,val);    update(now);}void qjadd(int now,int l,int r,int ll,int rr,LL val){    if (ll<=l&&r<=rr) {        tr[now]=(LL)(tr[now]+(LL)(r-l+1)*val%p);        if (tr[now]>=p) tr[now]-=p;        add[now]+=val;        if (add[now]>=p) add[now]-=p;        return;    }    int mid=(l+r)/2;    pushdown(now,l,r);    if (ll<=mid) qjadd(now<<1,l,mid,ll,rr,val);    if (rr>mid) qjadd(now<<1|1,mid+1,r,ll,rr,val);    update(now);    //cout<<l<<" "<<r<<" "<<tr[now]<<endl;}LL qjsum(int now,int l,int r,int ll,int rr){    if (ll<=l&&r<=rr) return tr[now];    int mid=(l+r)/2; LL ans=0;    pushdown(now,l,r);    if (ll<=mid) ans+=qjsum(now<<1,l,mid,ll,rr); ans%=p;    if (rr>mid) ans+=qjsum(now<<1|1,mid+1,r,ll,rr); ans%=p;    return ans;}int main(){    freopen("a.in","r",stdin);    //freopen("my.out","w",stdout);    scanf("%d%lld",&n,&p);    for (int i=1;i<=n;i++) scanf("%d",&a[i]);    build(1,1,n);    scanf("%d",&m);    for (int i=1;i<=m;i++) {        int opt,x,y,z;        scanf("%d%d%d",&opt,&x,&y);        if (opt==2) {            scanf("%d",&z);            qjadd(1,1,n,x,y,z);        //  cout<<tr[1]<<endl;        }        if (opt==1) {            scanf("%d",&z);            qjmul(1,1,n,x,y,z);        }        if (opt==3) {            printf("%lld\n",qjsum(1,1,n,x,y)%p);        }    }}
0 0
原创粉丝点击