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

老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成。 有长为N的数列,不妨设为a1,a2,…,aN 。有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2)把数列中的一段数全部加一个值; (3)询问数列中的一段数的和,由于答案可能很大,你只需输出这个数模P的值。
题解:维护两种lazy标记即可由于比+优限级高,所以先pushdown的lazy,如果此时+的lazy还在,那么改一下+的lazy即可,然后pushdown+的lazy就不用递归pushdown了

/**************************************************************
    Problem: 1798
    User: walfy
    Language: C++
    Result: Accepted
    Time:5992 ms
    Memory:38792 kb
****************************************************************/
 
//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define vi vector<int>
#define mod 1000000007
#define ld long double
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
#define cd complex<double>
#define ull unsigned long long
#define base 1000000000000000000
#define fio ios::sync_with_stdio(false);cin.tie(0)
 
using namespace std;
 
const double eps=1e-6;
const int N=400000+10,maxn=2000000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f;
 
ll val[N<<2],lazy[N<<2][2],p;
void pushup(int rt)
{
    val[rt]=(val[rt<<1]+val[rt<<1|1])%p;
}
void pushdown(int l,int r,int rt)
{
    int m=(l+r)>>1;
    if(lazy[rt][0]!=1)
    {
        val[rt<<1]=val[rt<<1]*lazy[rt][0]%p;
        val[rt<<1|1]=val[rt<<1|1]*lazy[rt][0]%p;
 
        if(lazy[rt<<1][1]!=0)lazy[rt<<1][1]=lazy[rt<<1][1]*lazy[rt][0]%p;
        lazy[rt<<1][0]=lazy[rt<<1][0]*lazy[rt][0]%p;
 
        if(lazy[rt<<1|1][1]!=0)lazy[rt<<1|1][1]=lazy[rt<<1|1][1]*lazy[rt][0]%p;
        lazy[rt<<1|1][0]=lazy[rt<<1|1][0]*lazy[rt][0]%p;
        lazy[rt][0]=1;
    }
    if(lazy[rt][1]!=0)
    {
        val[rt<<1]=(val[rt<<1]+(m-l+1)*lazy[rt][1]%p)%p;
        val[rt<<1|1]=(val[rt<<1|1]+(r-m)*lazy[rt][1]%p)%p;
//        if(lazy[rt<<1][0]!=1&&l<r)pushdown(ls);
        lazy[rt<<1][1]=(lazy[rt<<1][1]+lazy[rt][1])%p;
//        if(lazy[rt<<1|1][0]!=1&&l<r)pushdown(rs);
        lazy[rt<<1|1][1]=(lazy[rt<<1|1][1]+lazy[rt][1])%p;
        lazy[rt][1]=0;
    }
}
void build(int l,int r,int rt)
{
    lazy[rt][0]=1;
    if(l==r)
    {
        scanf("%lld",&val[rt]);
        val[rt]%=p;
        return ;
    }
    int m=(l+r)>>1;
    build(ls);build(rs);
    pushup(rt);
}
void update(int L,int R,ll c,int op,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
        if(op==1)
        {
            if(lazy[rt][1]!=0)pushdown(l,r,rt);
            val[rt]=val[rt]*c%p,lazy[rt][0]=lazy[rt][0]*c%p;
        }
        else
        {
            if(lazy[rt][0]!=1)pushdown(l,r,rt);
            val[rt]=(val[rt]+(r-l+1)*c%p)%p;lazy[rt][1]=(lazy[rt][1]+c)%p;
        }
        return ;
    }
    pushdown(l,r,rt);
    int m=(l+r)>>1;
    if(L<=m)update(L,R,c,op,ls);
    if(m<R)update(L,R,c,op,rs);
    pushup(rt);
}
ll query(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R)return val[rt];
    pushdown(l,r,rt);
    int m=(l+r)>>1;
    ll ans=0;
    if(L<=m)ans=(ans+query(L,R,ls))%p;
    if(m<R)ans=(ans+query(L,R,rs))%p;
    return ans;
}
void debug(int l,int r,int rt)
{
    printf("%d %d %lld %lld %lld\n",l,r,val[rt],lazy[rt][0],lazy[rt][1]);
    if(l==r)return ;
    int m=(l+r)>>1;
    debug(ls);debug(rs);
}
int main()
{
    int n;
    scanf("%d%lld",&n,&p);
    build(1,n,1);
    int m;scanf("%d",&m);
    while(m--)
    {
//        debug(1,n,1);puts("+++++++++++");
        int op,l,r;
        scanf("%d%d%d",&op,&l,&r);
        if(op==1||op==2)
        {
            ll c;scanf("%lld",&c);
            update(l,r,c,op,1,n,1);
        }
        else printf("%lld\n",query(l,r,1,n,1));
    }
    return 0;
}
/********************
 
********************/
posted @ 2018-06-03 20:13  walfy  阅读(186)  评论(0编辑  收藏  举报