zoukankan      html  css  js  c++  java
  • 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
    ",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
    ",query(l,r,1,n,1));
        }
        return 0;
    }
    /********************
     
    ********************/
    
  • 相关阅读:
    X、Y轴抖动的动画
    ViewFlipper的简单用法
    让手机连接到指定的WIFI网络,适用于之前已经连过的网络
    Eclipse 离线汉化的方法
    自己写的SeekBarPreference,可以实现seekbar滑动监听和设置默认进度和最大进度
    录制Android屏幕软件——屏幕录像专家
    【转】解决Android因加载多个大图引起的OutOfMemoryError,内存溢出的问题
    Java中的线程实现
    获得手机当前的ip地址
    操作Wifi的工具类
  • 原文地址:https://www.cnblogs.com/acjiumeng/p/9130344.html
Copyright © 2011-2022 走看看