Lowbit(势能线段树)

D. Lowbit
time limit per test7 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
Lucida has a sequence of n integers a1,a2,…,an. He asks you to perform two types of operations for him, which are described as follows:

1. 1 L R, add lowbit(ai) to each ai in the interval [L,R].

2. 2 L R, query the sum of the numbers in the interval [L,R].

lowbit(x) is defined as the largest power of 2 that divides x. For example, lowbit(4)=4, lowbit(5)=1. Specially, lowbit(0)=0.

Lucida wants you to give the answer modulo 998244353 for each of his queries.

Input
This problem contains multiple test cases.

The first line contains a single integer T (1≤T≤20) indicating the number of test cases.

For each case, the first line contains an integer n (1≤n≤105), the length of the sequence.

The next line contains n integers ai (1≤ai<998244353) separated by spaces, representing the sequence.

The next line contains an integer m (1≤m≤105), the number of operations.

The next m lines, each line contains 3 integers op,L,R (1≤op≤2, 1≤L≤R≤n), represents one operation. The specific meaning is described above.

Output
For each query, output a line contains the answer modulo 998244353.

Example
inputCopy
1
5
1 2 3 4 5
5
2 2 4
1 1 3
2 2 4
1 1 5
2 4 5
outputCopy
9
12
14
View Problem
#include <bits/stdc++.h>
using namespace std;
#define M 100005
#define ri register int

const int mod=998244353;
template <class G> void read(G &x)
{
    x=0;char ch=getchar();int f=0;
    while(ch<'0'||ch>'9'){f|=ch=='-';ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    x=f?-x:x;
    return ;
}

int n,m;
long long  val[M];
struct dian{
    int l,r;
    long long sum;
    long long lz;
    int flag;
}p[4*M];

int ck(long long a)
{
    if(a==(a&(-a))) return 1;
    else return 0;
}
void build(int l,int r,int i)
{
    p[i].l=l,p[i].r=r;p[i].lz=1;
    if(l==r)
    {
        p[i].sum=val[l];
        p[i].flag=0;return ;
    }
    int mid=(l+r)>>1;
    build(l,mid,i<<1);
    build(mid+1,r,i<<1|1);
    p[i].sum=(p[i<<1].sum+p[i<<1|1].sum)%mod;
    p[i].flag=(p[i<<1].flag&p[i<<1|1].flag);
}
void downn(int i)
{
    if(p[i].lz==1) return ;
    p[i<<1].sum=(1LL*p[i<<1].sum*p[i].lz)%mod;
    p[i<<1|1].sum=(1LL*p[i<<1|1].sum*p[i].lz)%mod;
    p[i<<1].lz=p[i<<1].lz*p[i].lz%mod;
    p[i<<1|1].lz=p[i<<1|1].lz*p[i].lz%mod;
    p[i].lz=1;
}
void xiu(int l,int r,int i)
{
    if(l>p[i].r||r<p[i].l) return ;
    if(l<=p[i].l&&p[i].r<=r)
    {
        if(p[i].flag)
        {    
            p[i].sum=(1LL*p[i].sum*2)%mod;
            p[i].lz=p[i].lz*2%mod;
            return ;
        }
    }
    if(p[i].l==p[i].r)
    {
        p[i].sum=(p[i].sum+(p[i].sum&(-p[i].sum)));
        p[i].flag=ck(p[i].sum);
        return ;
    }
    downn(i);
    xiu(l,r,i<<1);xiu(l,r,i<<1|1);
    p[i].sum=(p[i<<1].sum+p[i<<1|1].sum)%mod;
    p[i].flag=(p[i<<1].flag&p[i<<1|1].flag);
}
long long cha(int l,int r,int i)
{
    if(l>p[i].r||r<p[i].l) return 0;
    if(l<=p[i].l&&p[i].r<=r)
    {
        return p[i].sum;
    }
    if(p[i].lz) downn(i);
    return (cha(l,r,i<<1)+cha(l,r,i<<1|1))%mod;
}
int T;
int main(){
    
    read(T);
    while(T--)
    {
        
        read(n);
        for(ri i=1;i<=n;i++) read(val[i]);
        build(1,n,1);
        read(m);
        for(ri i=1;i<=m;i++)
        {
            int a,b,c;
            read(a);read(b);read(c);
            if(a==1)
            {
                xiu(b,c,1);
            }
            if(a==2)
            {
                long long ans=cha(b,c,1);
                ans=ans%mod;
                printf("%lld\n",ans);
            }
        }    
    }
}
View Code

 

思路: 

  • 牢牢利用lowbit的性质,当 x=lowbit时,相当于 x2, 之后每一次lowbit 都是x2.
  • 注意这个取模,不用对基本单位取模,应为他要lowbit,lz一定要取模

反思:

  • 当答案错误时,发现没有代码错误时。
  • 就一定是 某些没有考虑完全,思路完全了吗?,一些细节完全了吗,这道题 lz要取mod,不能直接 <<lazy 这要一下子就要爆炸。
posted @ 2022-03-11 18:02  VxiaohuanV  阅读(72)  评论(0编辑  收藏  举报