BZOJ 1798 维护序列

Posted on 2016-05-11 21:25  ziliuziliu  阅读(172)  评论(0编辑  收藏  举报

我偏要先下传加。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 100500
using namespace std;
long long ls[maxn<<2],rs[maxn<<2],val[maxn<<2],lazy1[maxn<<2],lazy2[maxn<<2];
long long n,p,m,a,b,c,d,w[maxn],tot=0,root;
void pushup(long long now)
{
    val[now]=(val[ls[now]]+val[rs[now]])%p;
}
void build(long long &now,long long left,long long right)
{
    now=++tot;lazy1[now]=0;lazy2[now]=1;
    if (left==right)
    {
        val[now]=w[left]%p;
        return;
    }
    long long mid=(left+right)>>1;
    build(ls[now],left,mid);
    build(rs[now],mid+1,right);
    pushup(now);
}
void pushdown(long long now,long long left,long long right)
{
    long long mid=(left+right)>>1;
    lazy1[ls[now]]=(lazy1[ls[now]]*lazy2[now]+lazy1[now])%p;
    lazy1[rs[now]]=(lazy1[rs[now]]*lazy2[now]+lazy1[now])%p;
    lazy2[ls[now]]=(lazy2[ls[now]]*lazy2[now])%p;
    lazy2[rs[now]]=(lazy2[rs[now]]*lazy2[now])%p;
    val[ls[now]]=(val[ls[now]]*lazy2[now]+lazy1[now]*(mid-left+1))%p;
    val[rs[now]]=(val[rs[now]]*lazy2[now]+lazy1[now]*(right-mid))%p;
    lazy1[now]=0;lazy2[now]=1;
}
void modify(long long now,long long left,long long right,long long l,long long r,long long type,long long x)
{
    pushdown(now,left,right);
    if ((left==l) && (right==r))
    {
        if (type==1) {lazy1[now]+=x;lazy1[now]%=p;val[now]+=x*(right-left+1);val[now]%=p;}
        else {lazy2[now]*=x;lazy2[now]%=p;lazy1[now]*=x;lazy1[now]%=p;val[now]*=x;val[now]%=p;}
        return;
    }
    long long mid=(left+right)>>1;
    if (r<=mid) modify(ls[now],left,mid,l,r,type,x);
    else if (l>=mid+1) modify(rs[now],mid+1,right,l,r,type,x);
    else
    {
        modify(ls[now],left,mid,l,mid,type,x);
        modify(rs[now],mid+1,right,mid+1,r,type,x);
    }
    pushup(now);
}
long long ask(long long now,long long left,long long right,long long l,long long r)
{
    pushdown(now,left,right);
    if ((left==l) && (right==r))
        return val[now]%p;
    long long mid=(left+right)>>1;
    if (r<=mid) return ask(ls[now],left,mid,l,r)%p;
    else if (l>=mid+1) return ask(rs[now],mid+1,right,l,r)%p;
    else return (ask(ls[now],left,mid,l,mid)+ask(rs[now],mid+1,right,mid+1,r))%p;
}
void work1()
{
    scanf("%lld%lld%lld",&b,&c,&d);
    modify(root,1,n,b,c,2,d);
}
void work2()
{
    scanf("%lld%lld%lld",&b,&c,&d);
    modify(root,1,n,b,c,1,d);
}
void work3()
{
    scanf("%lld%lld",&b,&c);
    printf("%lld\n",ask(root,1,n,b,c)%p);
}
int main()
{
    scanf("%lld%lld",&n,&p);
    for (long long i=1;i<=n;i++)
        scanf("%lld",&w[i]);
    build(root,1,n);
    scanf("%lld",&m);
    for (long long i=1;i<=m;i++)
    {
        scanf("%lld",&a);
        if (a==1) work1();
        else if (a==2) work2();
        else work3();
    }
    return 0;
}