1. 程式人生 > 其它 >Lowbit(勢能線段樹)

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 這要一下子就要爆炸。