[Lowbit]

[Lowbit]( Problem - 7116 (hdu.edu.cn) )

思路:一个数加上log次lowbit后就会成2的次方,那么用线段树维护区间和同时维护这个区间内所有的数是否是2的次方,若是,打懒标记将这个区间*2,否则暴力更新叶节点。

#include<bits/stdc++.h>
#define mid ((t[p].l+t[p].r)>>1)
#define ll long long
#define ls (p<<1)
#define rs ((p<<1)|1)
#define ll long long 
#define pb push_back
using namespace std;
ll read(){ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f;}
inline void Prin(ll x){if(x < 0){putchar('-');x = -x;}if(x > 9) Prin(x / 10);putchar(x % 10 + '0');}

const int qs=2e5+7;
const ll mod=998244353;
struct Tree{
    int l,r;
    ll val,add,tag;
    #define l(x) t[x].l
    #define r(x) t[x].r
    #define val(x) t[x].val
    #define add(x) t[x].add
    #define tag(x) t[x].tag
}t[qs*4];
ll T,n,a[qs],q;

void pushup(int p) { 
    val(p)=(val(ls)+val(rs))%mod;
    tag(p)=tag(ls)+tag(rs);
}

ll lowbit(ll x){
    return (x&(-x));
}

void build(int p,int l,int r){
    l(p)=l,r(p)=r; add(p)=1;
    if(l==r){
        val(p)=a[l];
        tag(p)=lowbit(a[l])==a[l] ? 0 : 1;
        return;
    }
    build(ls,l,mid);
    build(rs,mid+1,r);
    pushup(p);

}

void down(int p){
    if(add(p)==1) return;
    val(ls)=val(ls)*add(p)%mod;
    val(rs)=val(rs)*add(p)%mod;
    add(ls)=add(ls)*add(p)%mod;
    add(rs)=add(rs)*add(p)%mod;
    add(p)=1; 
}
void update(int p,int l,int r){
    
//    cout<<"l="<<l(p)<<" r="<<r(p)<<" val="<<val(p)<<"\n";
    if(l<=l(p)&&r>=r(p)){
        if(tag(p)==0){
            add(p)=add(p)*2%mod;
            val(p)=val(p)*2%mod;
            return;
        }
        if(l(p)==r(p)){
            ll vp=lowbit(a[l(p)]);
            a[l(p)]+=vp;
            val(p)=a[l(p)]%mod;
            if(lowbit(a[l(p)])==a[l(p)]) tag(p)=0;
            return ;
        }
        down(p);
        update(ls,l,r);
        update(rs,l,r);
        pushup(p);
        return;
    }
    down(p);
    if(l<=mid) update(ls,l,r);
    if(r>mid) update(rs,l,r);
    pushup(p);
}
ll ask(int p,int l, int r){
    if(l<=l(p)&&r>=r(p)) return val(p);
    down(p);
    ll val=0;
    if(l<=mid) val+=ask(ls,l,r);
    if(r>mid) val+=ask(rs,l,r);
    val%=mod;
    return val;
}
int main(){
    T=read();
    while(T--){
        n=read();
        for(int i=1;i<=n;++i) a[i]=read();
        build(1,1,n);
        q=read();
        while(q--){
            int x,l,r;
            x=read(),l=read(),r=read();
            if(x==1){
                update(1,l,r);    
            } 
            else{
                ll ans=ask(1,l,r);
                Prin(ans);
                puts("");
            }
        }
    }
    return 0;
}

posted @ 2021-09-05 21:52  Suki_Sugar  阅读(28)  评论(0编辑  收藏  举报
Live2D