[BZOJ1798][Ahoi2009]Seq 维护序列seq

原题地址

线段树模(mu)板题.

AC code:

#include <cstdio>
typedef long long ll;
const int N=100010;
ll n,q,m,tot;
ll a[N];

struct nod{
    ll  l,r,sum,tmul,tadd;
    nod *lc,*rc;
}pool[N<<3];

struct Segtree{
    nod *root;

    Segtree(){
        build(&root,1,n);
    }

    void build(nod **p,ll L,ll R){
        *p=&pool[tot++];(*p)->l=L;(*p)->r=R;(*p)->tmul=1;
        if(L==R){
            (*p)->sum=a[L]%q;
            return ;
        }
        ll M=(L+R)>>1;
        build(&(*p)->lc,L,M);
        build(&(*p)->rc,M+1,R);
        (*p)->sum=((*p)->lc->sum+(*p)->rc->sum)%q;
    }
    void clear(nod *p){
        if(p->l!=p->r){
            p->lc->tmul=(p->lc->tmul*p->tmul)%q;
            p->lc->tadd=(p->lc->tadd*p->tmul)%q;
            p->rc->tmul=(p->rc->tmul*p->tmul)%q;
            p->rc->tadd=(p->rc->tadd*p->tmul)%q;
            p->lc->tadd=(p->lc->tadd+p->tadd)%q;
            p->rc->tadd=(p->rc->tadd+p->tadd)%q;
        }
        p->sum=(p->sum*p->tmul+(p->r-p->l+1)*p->tadd)%q;
        p->tadd=0;p->tmul=1;
    }
    void mul(nod *p,ll L,ll R,ll v){
        clear(p);
        if(p->l==L&&p->r==R){
            p->tmul=v;
            return ;
        }
        ll M=(p->l+p->r)>>1;
        if(R<=M) mul(p->lc,L,R,v);
        else if(L>M) mul(p->rc,L,R,v);
        else{
            mul(p->lc,L,M,v);
            mul(p->rc,M+1,R,v);
        }
        clear(p->lc);clear(p->rc);
        p->sum=(p->lc->sum+p->rc->sum)%q;
    }
    void add(nod *p,ll L,ll R,ll v){
        clear(p);
        if(p->l==L&&p->r==R){
            p->tadd=v;
            return ;
        }
        ll M=(p->l+p->r)>>1;
        if(R<=M) add(p->lc,L,R,v);
        else if(L>M) add(p->rc,L,R,v);
        else{
            add(p->lc,L,M,v);
            add(p->rc,M+1,R,v);
        }
        clear(p->lc);clear(p->rc);
        p->sum=(p->lc->sum+p->rc->sum)%q;
    }
    ll query(nod *p,ll L,ll R){
        clear(p);
        if(p->l==L&&p->r==R) return p->sum%q;
        ll M=(p->l+p->r)>>1;
        if(R<=M) return query(p->lc,L,R)%q;
        else if(L>M) return query(p->rc,L,R)%q;
        else return (query(p->lc,L,M)+query(p->rc,M+1,R))%q;
    }
};

int main(){
    scanf("%lld%lld",&n,&q);
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    Segtree T;
    scanf("%lld",&m);
    for(int i=1;i<=m;i++){
        ll t,L,R,v;
        scanf("%lld%lld%lld",&t,&L,&R);
        if(t!=3){
            scanf("%lld",&v);
            if(t==1) T.mul(T.root,L,R,v);
            else T.add(T.root,L,R,v);
        }
        else printf("%lld\n",T.query(T.root,L,R));
    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值