HDU7116lowbit(暴力+线段树)

题目大意:
lowbit(x)是x的最低位1 区间修改 ai+lowbit(ai) 区间和查询 n,m<1e5
题解:
一个数x最多加log(x)次lowbitx就会变成2的幂,2的幂加lowbitx相当于x2,标记区间是否都为2的幂,若是则区间每个数x2,不是则暴力修改。

#include<bits/stdc++.h>
using namespace std;
#define LL long long

const int N=1e5+7;

const int mod=998244353;

int n;
int m,od,l,r;
LL a[N];

struct Tree
{
    int l,r;
    LL sum;
    bool gg;
    LL flag;
}tr[N<<2];


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

void pushup(int rt)
{
    tr[rt].sum=(tr[rt<<1].sum%mod+tr[rt<<1|1].sum%mod)%mod;
    tr[rt].gg=min(tr[rt<<1].gg,tr[rt<<1|1].gg);
}

void pushdown(int rt)
{
    if(tr[rt].flag==1)return ;
    tr[rt<<1].sum=tr[rt<<1].sum*tr[rt].flag%mod;
    tr[rt<<1|1].sum=tr[rt<<1|1].sum*tr[rt].flag%mod;
    tr[rt<<1].flag=tr[rt<<1].flag*tr[rt].flag%mod;
    tr[rt<<1|1].flag=tr[rt<<1|1].flag*tr[rt].flag%mod;
    tr[rt].flag=1;
}

void build(int rt,int l,int r)
{
    tr[rt].l=l;tr[rt].r;tr[rt].flag=1;
    if(l==r)
    {
        tr[rt].sum=a[l];
          tr[rt].gg=0;
        return ;
    }
    int mid=(l+r)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
    pushup(rt);
}

void update(int rt,int l,int r,int ql,int qr)
{
    if(ql<=l&&qr>=r&&tr[rt].gg==1)
    {
        tr[rt].sum=tr[rt].sum*2%mod;
        tr[rt].flag=tr[rt].flag*2%mod;
        return ;
    }
    if(l==r)
    {
        tr[rt].sum=tr[rt].sum+lowbit(tr[rt].sum);
        if(tr[rt].sum==lowbit(tr[rt].sum)) tr[rt].gg=1;
        return ;
    }
    pushdown(rt);
    int mid=(l+r)>>1;
    if(ql<=mid) update(rt<<1,l,mid,ql,qr);
    if(qr>mid) update(rt<<1|1,mid+1,r,ql,qr);
    pushup(rt);
}

LL query(int rt,int l,int r,int ql,int qr)
{
    if(ql<=l&&qr>=r) return tr[rt].sum;
    pushdown(rt);
    LL res=0;
    int mid=(l+r)>>1;
    if(ql<=mid) res=(res%mod+query(rt<<1,l,mid,ql,qr)%mod)%mod;
    if(qr>mid) res=(res%mod+query(rt<<1|1,mid+1,r,ql,qr)%mod)%mod;
    return res;
}

int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
        build(1,1,n);
        scanf("%d",&m);
        while(m--)
        {
            scanf("%d%d%d",&od,&l,&r);
            if(od==1)
            {
                update(1,1,n,l,r);
            }else
            {
                printf("%lld\n",query(1,1,n,l,r));
            }
        }
    }
    return 0;
}

posted @ 2021-09-05 18:58  ANhour  阅读(115)  评论(0编辑  收藏  举报