zoukankan      html  css  js  c++  java
  • luogu P2023 [AHOI2009] 维护序列

    luogu P2023 [AHOI2009] 维护序列

    题意:

    有一个长为 n 的数列 ({a_n}),有如下三种操作形式:
    1 格式 1 t g c,表示把所有满足 (tle ile g)(a_i) 改为 (a_i imes c) ;
    2 格式 2 t g c 表示把所有满足 (tle ile g)(a_i) 改为 (a_i+c) ;
    3 格式 3 t g 询问所有满足 (tle ile g)(a_i) 的和,由于答案可能很大,你只需输出这个数模 (p) 的值

    思路:

    第一眼看上去 ,裸线段树吧
    但其实也有很多 细节
    因为乘法和加法是同时存在的
    所以加法与乘法的优先级就不一样,在你的程序中先算谁后算谁,答案都是不一样的
    想一个事

    如果对一个数先加再乘(ans=(a+b)*c=a*c+b*c) 对一个数先乘后加(ans=a*b+c)
    那么在(add) (mul)标记同时存在时,先下放(add)标记是不对的 (ans=(a+b)*c ,ans=(a+c)*b)第二个式子就不对了,且无法补救
    那先下放mul标记呢,对于第一个式子如果(ans=a*c)后让(add*=c),然后再下放(add) (ans=a*c+b*c) 完美 第二个式子,(ans=a*b+c)
    那么问题就解决了,如果是加法,就直接加,如果是乘法,先把(add*=c)

    对于push_down函数,每个儿子的(x)(tree[now<<1].x=(tree[now<<1].x*tree[now].mul\%mod+(tree[now<<1].r-tree[now<<1].l+1)*tree[now].add\%mod)\%mod);
    因为对于每个(add),我们都是进行过处理的,所以直接去先算(mul)就可以,然后再加上底下的(add)的那些差值

    //(add)是加法标记,(mul)是乘法标记,(x)是当前线段树维护值

    说来说去 还是个裸线段树,一个(tree[now])写成(tree[now<<1]),我debug要瞎了

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define lowbit(a) ((a) & -(a))
    #define clean(a, b) memset(a, b, sizeof(a))
    // const ll mod = 1e9 + 7;
    const int inf = 0x3f3f3f3f;
    const int maxn = 2e5 + 9;
    
    ll _;
    
    //========================================================================
    int mod,a[maxn];
    struct node
    {
        ll l,r,x,add,mul;
    }tree[maxn<<2];
    void build(ll l,ll r,ll now)
    {
        tree[now].l=l;
        tree[now].r=r;
        tree[now].mul=1;
        if(l==r) 
        {
            tree[now].x=a[l]%mod;
            return ;
        }
        ll mid=(l+r)>>1;
        build(l,mid,now<<1);
        build(mid+1,r,now<<1|1);
        tree[now].x=(tree[now<<1].x+tree[now<<1|1].x)%mod;
    }
    void push_down(ll now)
    {
        tree[now<<1].x=(tree[now<<1].x*tree[now].mul%mod+(tree[now<<1].r-tree[now<<1].l+1)*tree[now].add%mod)%mod;
        tree[now<<1|1].x=(tree[now<<1|1].x*tree[now].mul%mod+(tree[now<<1|1].r-tree[now<<1|1].l+1)*tree[now].add%mod)%mod;
    
        tree[now<<1].mul=(tree[now<<1].mul*tree[now].mul)%mod;
        tree[now<<1|1].mul=(tree[now<<1|1].mul*tree[now].mul)%mod;
        
        tree[now<<1].add=(tree[now<<1].add*tree[now].mul+tree[now].add)%mod;
        tree[now<<1|1].add=(tree[now<<1|1].add*tree[now].mul+tree[now].add)%mod;
    
        tree[now].add=0;
        tree[now].mul=1;
    }
    
    void update_add(ll l,ll r,ll now,ll c)
    {
        if(l==tree[now].l&&r==tree[now].r)
        {
            tree[now].x=(tree[now].x+c*(r-l+1)%mod)%mod;
            tree[now].add=(tree[now].add+c)%mod;
            return ;
        }
         push_down(now);
        tree[now].x=(tree[now<<1].x+tree[now<<1|1].x)%mod;
        ll mid=(tree[now].l+tree[now].r)>>1;
        if(r<=mid) update_add(l,r,now<<1,c);
        else if(l>mid) update_add(l,r,now<<1|1,c);
        else 
        {
            update_add(l,mid,now<<1,c);
            update_add(mid+1,r,now<<1|1,c);
        }
        tree[now].x=(tree[now<<1].x+tree[now<<1|1].x)%mod;
    }
    void update_mul(ll l,ll r,ll now,ll c)
    {
        if(l==tree[now].l&&r==tree[now].r)
        {
            tree[now].add=(tree[now].add*c)%mod;
            tree[now].mul=(tree[now].mul*c)%mod;
            tree[now].x=(tree[now].x*c)%mod;
            return ;
        }
        push_down(now);
        tree[now].x=(tree[now<<1].x+tree[now<<1|1].x)%mod;
        ll mid=(tree[now].l+tree[now].r)>>1;
        if(r<=mid) update_mul(l,r,now<<1,c);
        else if(l>mid) update_mul(l,r,now<<1|1,c);
        else 
        {
            update_mul(l,mid,now<<1,c);
            update_mul(mid+1,r,now<<1|1,c);
        }
        tree[now].x=(tree[now<<1].x+tree[now<<1|1].x)%mod;
    }
    ll query(ll l,ll r,ll now)
    {
        if(l==tree[now].l&&r==tree[now].r) 
        {
            return tree[now].x;
        }
        push_down(now);
        tree[now].x=(tree[now<<1].x+tree[now<<1|1].x)%mod;
        ll mid=(tree[now].l+tree[now].r)>>1;
        if(r<=mid) return query(l,r,now<<1);
        else if(l>mid) return query(l,r,now<<1|1);
        else return (query(l,mid,now<<1)+query(mid+1,r,now<<1|1))%mod;
    }
    //========================================================================
    int main()
    {
        ll n,p,op;
        scanf("%lld%lld",&n,&mod);
        for(ll i=1;i<=n;i++) scanf("%lld",&a[i]);
        build(1,n,1);
        ll q,l,r,c;
        scanf("%lld",&q);
        while(q--)
        {
            scanf("%lld",&op);
            if(op==1) 
            {
                scanf("%lld%lld%lld",&l,&r,&c);
                update_mul(l,r,1,c);
            }
            else if(op==2)
            {
                scanf("%lld%lld%lld",&l,&r,&c);
                update_add(l,r,1,c);
            }
            else 
            {
                scanf("%lld%lld",&l,&r);
                printf("%lld
    ",query(l,r,1));
            }
        }
        return 0;
    }
    
  • 相关阅读:
    mysql 远程登陆不上
    hdu 5339 Untitled【搜索】
    SqlServer 书目
    passwordauthentication yes
    oracle 11g RAC ocfs2
    Oracle 11g RAC database on ASM, ACFS or OCFS2
    CentOS ips bonding
    Oracle 11g RAC features
    openStack 王者归来之 trivial matters
    openstack windows 2008 img
  • 原文地址:https://www.cnblogs.com/YangKun-/p/13435271.html
Copyright © 2011-2022 走看看