[线段树]JZOJ 5943 树
分析
不修改应该都会吧,就是线段树
然后带修改,我们可以把每次要and的数和该区间的或和and一次,如果没有变化可以不进行这次修改
然后可以证明一个数最多减小logn次
那么暴力修改即可
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <cstdio> using namespace std; typedef long long ll; const ll P=998244353; const int N=1e5+10; ll sqr[4*N],sum[4*N],_or[4*N]; ll a[N]; int n,q; void Build(int x,int l,int r) { if (l==r) { sqr[x]=a[l]*a[l]%P;sum[x]=a[l];_or[x]=a[l]; return; } int mid=l+r>>1; Build(x<<1,l,mid); Build((x<<1)+1,mid+1,r); sqr[x]=(sqr[x<<1]+sqr[(x<<1)+1])%P; sum[x]=sum[x<<1]+sum[(x<<1)+1]; _or[x]=_or[x<<1]|_or[(x<<1)+1]; } void Pushdown(int x,int l,int r,ll k) { if (_or[x]==(_or[x]&k)) return; if (l==r) { a[l]&=k;sqr[x]=a[l]*a[l]%P;sum[x]=a[l];_or[x]=a[l]; return; } int mid=l+r>>1; Pushdown(x<<1,l,mid,k); Pushdown((x<<1)+1,mid+1,r,k); sqr[x]=(sqr[x<<1]+sqr[(x<<1)+1])%P; sum[x]=sum[x<<1]+sum[(x<<1)+1]; _or[x]=_or[x<<1]|_or[(x<<1)+1]; } void Change(int x,int l,int r,int lll,int rr,ll k) { if (l>rr||lll>r) return; if (_or[x]==(_or[x]&k)) return; if (lll<=l&&r<=rr) { Pushdown(x,l,r,k); return; } int mid=l+r>>1; if (lll<=mid) Change(x<<1,l,mid,lll,rr,k); if (mid<rr) Change((x<<1)+1,mid+1,r,lll,rr,k); sqr[x]=(sqr[x<<1]+sqr[(x<<1)+1])%P; sum[x]=sum[x<<1]+sum[(x<<1)+1]; _or[x]=_or[x<<1]|_or[(x<<1)+1]; } ll Query_sqr(int x,int l,int r,int lll,int rr) { if (l>rr||lll>r) return 0; if (lll<=l&&r<=rr) return sqr[x]; int mid=l+r>>1; ll ans=0; if (lll<=mid) ans=Query_sqr(x<<1,l,mid,lll,rr)%P; if (mid<rr) (ans+=Query_sqr((x<<1)+1,mid+1,r,lll,rr))%=P; return ans; } ll Query_sum(int x,int l,int r,int lll,int rr) { if (l>rr||lll>r) return 0; if (lll<=l&&r<=rr) return sum[x]; int mid=l+r>>1; ll ans=0; if (lll<=mid) ans=Query_sum(x<<1,l,mid,lll,rr); if (mid<rr) ans+=Query_sum((x<<1)+1,mid+1,r,lll,rr); return ans; } int main() { freopen("seg.in","r",stdin); freopen("seg.out","w",stdout); scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%lld",&a[i]); Build(1,1,n); scanf("%d",&q); while (q--) { int order,l,r; scanf("%d%d%d",&order,&l,&r); if (order==1) { ll k;scanf("%lld",&k); Change(1,1,n,l,r,k); } else if (order==2) printf("%lld\n",Query_sum(1,1,n,l,r)); else { ll a=Query_sqr(1,1,n,l,r),b=Query_sum(1,1,n,l,r)%P; printf("%lld\n",(a*2ll*(r-l+1)%P+b*b*2ll%P)%P); } } }
在日渐沉没的世界里,我发现了你。