bzoj1798: [Ahoi2009]Seq 维护序列seq 线段树

题目传送门

这道题就是线段树 先传乘法标记再传加法

#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
const int M=400010;
LL read(){
    LL ans=0,f=1,c=getchar();
    while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();}
    return ans*f;
}
LL n,m,mod,L,R;
struct node{
    int l,r;
    LL sum,add,mt;
}tr[M];
void up(int x){tr[x].sum=(tr[x<<1].sum+tr[x<<1^1].sum)%mod;}
void cal(LL x,LL mt,LL w){
    if(!x) return ;
    LL l=tr[x].r-tr[x].l+1;
    tr[x].sum=(tr[x].sum*mt+w*l)%mod;
    tr[x].add=(tr[x].add*mt+w)%mod;
    tr[x].mt=tr[x].mt*mt%mod;
}
void down(LL x){
    if(tr[x].add||tr[x].mt!=1){
        cal(x<<1,tr[x].mt,tr[x].add);
        cal(x<<1^1,tr[x].mt,tr[x].add);
        tr[x].add=0; tr[x].mt=1;
    }
}
void build(LL x,LL l,LL r){
    tr[x].l=l; tr[x].r=r; tr[x].mt=1;
    if(l==r){tr[x].sum=read(); return ;}
    int mid=(l+r)>>1;
    build(x<<1,l,mid); build(x<<1^1,mid+1,r);
    up(x);
}
void push_mm(LL x,LL w){
    if(L<=tr[x].l&&tr[x].r<=R){cal(x,w,0); return ;}
    int mid=(tr[x].l+tr[x].r)>>1;
    down(x);
    if(L<=mid) push_mm(x<<1,w);
    if(R>mid) push_mm(x<<1^1,w);
    up(x);
}
void push_add(LL x,LL w){
    if(L<=tr[x].l&&tr[x].r<=R){cal(x,1,w); return ;}
    int mid=(tr[x].l+tr[x].r)>>1;
    down(x);
    if(L<=mid) push_add(x<<1,w);
    if(R>mid) push_add(x<<1^1,w);
    up(x);
}
LL push_sum(LL x){
    if(L<=tr[x].l&&tr[x].r<=R) return tr[x].sum;
    int mid=(tr[x].l+tr[x].r)>>1;
    down(x);
    LL ans=0;
    if(L<=mid) ans=(ans+push_sum(x<<1))%mod;
    if(R>mid)  ans=(ans+push_sum(x<<1^1))%mod;
    return ans;
}
int main()
{
    LL k,w; 
    n=read(); mod=read(); 
    build(1,1,n); 
    m=read();
    for(int i=1;i<=m;i++){
        k=read(); L=read(); R=read();
        if(k==1) w=read(),push_mm(1,w);
        if(k==2) w=read(),push_add(1,w);
        if(k==3) printf("%lld\n",push_sum(1)%mod);
    }
    return 0;
}
View Code

 

posted @ 2017-06-27 21:54  友人Aqwq  阅读(111)  评论(0编辑  收藏  举报