https://acm.hdu.edu.cn/showproblem.php?pid=7059
支持三种操作:1、区间求和 2、区间减lowbit 3、区间加$2^k(2^kle 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 ",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/+
+++++++++++++++++++++++++++++++++++++++++++