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

来源:互联网 发布:手指泡水起皱 知乎 编辑:程序博客网 时间:2024/06/08 18:34

注意标记的优先级问题。

#include<iostream>#include<cstdio>#define ll long long #define N 100005using namespace std;int n,m,P;int a[N];int l[N<<2],r[N<<2];ll sum[N<<2],tag_add[N<<2],tag_mul[N<<2];inline int read(){    int a=0,f=1; char c=getchar();    while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}    return a*f;}inline void pushup(int k){    sum[k]=(sum[k<<1]+sum[k<<1|1])%P;}inline void pushdown(int k){    sum[k<<1]=(sum[k<<1]*tag_mul[k]+(r[k<<1]-l[k<<1]+1)*tag_add[k])%P;    tag_mul[k<<1]=(tag_mul[k<<1]*tag_mul[k])%P;    tag_add[k<<1]=(tag_add[k<<1]*tag_mul[k]+tag_add[k])%P;    sum[k<<1|1]=(sum[k<<1|1]*tag_mul[k]+(r[k<<1|1]-l[k<<1|1]+1)*tag_add[k])%P;    tag_mul[k<<1|1]=(tag_mul[k<<1|1]*tag_mul[k])%P;    tag_add[k<<1|1]=(tag_add[k<<1|1]*tag_mul[k]+tag_add[k])%P;      tag_mul[k]=1; tag_add[k]=0;}void build(int k,int x,int y){    l[k]=x; r[k]=y; tag_mul[k]=1; tag_add[k]=0;     if (l[k]==r[k]) {sum[k]=a[l[k]]; return;}    int mid=l[k]+r[k]>>1;    build(k<<1,x,mid); build(k<<1|1,mid+1,y);    pushup(k);}void change(int k,int x,int y,int mul,int add){    if (l[k]==x&&r[k]==y)    {        sum[k]=(sum[k]*mul+(r[k]-l[k]+1)*add)%P;        tag_mul[k]=(tag_mul[k]*mul)%P;        tag_add[k]=(tag_add[k]*mul+add)%P;        return;    }    pushdown(k);    int mid=l[k]+r[k]>>1;    if (y<=mid) change(k<<1,x,y,mul,add);    else if (x>mid) change(k<<1|1,x,y,mul,add);    else change(k<<1,x,mid,mul,add),change(k<<1|1,mid+1,y,mul,add);    pushup(k);}ll query(int k,int x,int y){    if (l[k]==x&&r[k]==y) return sum[k];    pushdown(k);    int mid=l[k]+r[k]>>1;    if (y<=mid) return query(k<<1,x,y);    else if (x>mid) return query(k<<1|1,x,y);    else return (query(k<<1,x,mid)+query(k<<1|1,mid+1,y))%P;}int main(){    n=read(); P=read();    for (int i=1;i<=n;i++) a[i]=read();    build(1,1,n);    m=read();    for (int i=1;i<=m;i++)    {        int opt=read(),x=read(),y=read();        if (opt==3) printf("%lld\n",query(1,x,y));        else         {            int c=read();            if (opt==1) change(1,x,y,c,0);            else change(1,x,y,1,c);        }    }    return 0;}
0 0
原创粉丝点击