HDU7059:Counting Stars——题解

https://acm.hdu.edu.cn/showproblem.php?pid=7059

支持三种操作:1、区间求和 2、区间减lowbit 3、区间加$2^k(2^k\le a_i<2^{k+1})$

SB题,就是老年选手有点敲不动线段树了(现在数据结构越来越不稳了DEBUG等一年……)。

减lowbit容易想到每个数最多减log次,因此暴力减维护对应区间是否全0即可。

区间加$2^k$也不难发现这相当于对数的最高位*2。

因此整体做法就是把每个数的最低位和最高位分开处理即可。

(如果码风不好那就会像我一样DE一年的BUG……)

#include<cmath>
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=1e5+5;
const ll p=998244353;
inline int read(){
    int X=0,w=0;char ch=0;
    while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
    while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}
ll qpow[N];
void init(){
    qpow[0]=1;
    for(int i=1;i<=100000;i++){
        qpow[i]=qpow[i-1]<<1;
        qpow[i]%=p;
    }
}
int n,q,b[N];
ll low[N<<2],high[N<<2],lazy[N<<2];
bool zero[N<<2];
ll geth(ll x){
    for(ll i=1;;++i){
        if(!(x>>i))return (1<<(i-1))&x;
    }
}
void build(int a,int l,int r){
    if(l==r){
        high[a]=geth(b[l]);low[a]=b[l]-high[a];zero[a]=0;
        return;
    }
    int mid=(l+r)>>1;
    build(a<<1,l,mid);build(a<<1|1,mid+1,r);
    lazy[a]=0;
    low[a]=low[a<<1]+low[a<<1|1];
    high[a]=(high[a<<1]+high[a<<1|1])%p;
    zero[a]=zero[a<<1]&zero[a<<1|1];
}
inline void push(int a,int l,int r,int mid){
    if(lazy[a]){
        high[a<<1]=high[a<<1]*qpow[lazy[a]]%p;
        high[a<<1|1]=high[a<<1|1]*qpow[lazy[a]]%p;
        lazy[a<<1]+=lazy[a];
        lazy[a<<1|1]+=lazy[a];
        lazy[a]=0;
    }
    return;
}
void modify1(int a,int l,int r,int l1,int r1){
    if(r<l1||r1<l)return;
    if(zero[a])return;
    if(l==r){
        ll del=b[l]&(-b[l]);
        b[l]-=del;
        if(!b[l]){
            high[a]=0;
            zero[a]=1;
        }else{
            low[a]-=del;
        }
        return;
    }
    int mid=(l+r)>>1;
    push(a,l,r,mid);
    modify1(a<<1,l,mid,l1,r1);modify1(a<<1|1,mid+1,r,l1,r1);
    low[a]=low[a<<1]+low[a<<1|1];
    high[a]=(high[a<<1]+high[a<<1|1])%p;
    zero[a]=zero[a<<1]&zero[a<<1|1];
}
void modify2(int a,int l,int r,int l1,int r1){
    if(r<l1||r1<l)return;
    if(zero[a])return;
    if(l1<=l&&r<=r1){
        ++lazy[a];
        high[a]=(high[a]<<1)%p;
        return;
    }
    int mid=(l+r)>>1;
    push(a,l,r,mid);
    modify2(a<<1,l,mid,l1,r1);modify2(a<<1|1,mid+1,r,l1,r1);
    low[a]=low[a<<1]+low[a<<1|1];
    high[a]=(high[a<<1]+high[a<<1|1])%p;
    zero[a]=zero[a<<1]&zero[a<<1|1];
}
ll query(int a,int l,int r,int l1,int r1){
    if(r<l1||r1<l)return 0;
    if(zero[a])return 0;
    if(l1<=l&&r<=r1){
        return (high[a]+low[a])%p;
    }
    int mid=(l+r)>>1;
    push(a,l,r,mid);
    return (query(a<<1,l,mid,l1,r1)+query(a<<1|1,mid+1,r,l1,r1))%p;
}
int main(){
    init();
    int T=read();
    while(T--){
        n=read();
        for(int i=1;i<=n;i++)b[i]=read();
        build(1,1,n);
        q=read();
        while(q--){
            int op=read(),l=read(),r=read();
            if(op==1){
                printf("%d\n",query(1,1,n,l,r));
            }
            if(op==2){
                modify1(1,1,n,l,r);
            }
            if(op==3){
                modify2(1,1,n,l,r);
            }
        }
    }
    return 0;
}

+++++++++++++++++++++++++++++++++++++++++++

 +本文作者:luyouqi233。               +

 +欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

+++++++++++++++++++++++++++++++++++++++++++

posted @ 2021-08-12 17:18  luyouqi233  阅读(90)  评论(0编辑  收藏  举报