题目链接:SDUT 2023 summer team contest(for 22) - 5 - Virtual Judge (vjudge.net)
思路:因为一个数不断进行lowbit最后得到的数将会是lowbit之前的数,也就是相加后是之前一个数的二倍,可以优先处理这些数,最后二倍 的处理区间。
代码:
#include <bits/stdc++.h>
#define int long long
#define lowbit(x) ((x)&(-x))
#define dbug(x) cout<<#x<<'='<<x<<endl;
#define x first
#define y second
#define pb push_back
const int N = 1e5 + 5;
const int INF = 0x3f3f3f3f;
const int mod = 998244353;
using namespace std;
typedef pair<int, int>pii;
int n, m;
map<int, int>mp;
int a[N],b[N];
struct node{
int l,r,lazy,sum,pd;//lazy为懒标记,pd为判断是否已经和lowbit后相等
}g[N<<2];
void pushup(int i){
g[i].sum=(g[i<<1].sum+g[i<<1|1].sum)%mod;
g[i].pd=min(g[i<<1].pd,g[i<<1|1].pd);//判断该区间中的所有数是否和lowbit一样
}
void pushdown(int i){
if(g[i].lazy>1){
g[i<<1].sum=(g[i<<1].sum*g[i].lazy)%mod,g[i<<1].lazy=(g[i].lazy*g[i<<1].lazy)%mod;//懒标记向下继承,求出子区间的sum
g[i<<1|1].sum=(g[i<<1|1].sum*g[i].lazy)%mod,g[i<<1|1].lazy=(g[i].lazy*g[i<<1|1].lazy)%mod;
g[i].lazy=1;
}
}
void build(int i,int l,int r){
if(l==r)g[i].l=l,g[i].r=r,g[i].sum=a[l],g[i].lazy=1,g[i].pd=0;
else{
g[i].l=l,g[i].r=r,g[i].lazy=1;
int mid=l+r>>1;
build(i<<1,l,mid),build(i<<1|1,mid+1,r);
pushup(i);
}
}
void modify(int i,int l,int r){
if(g[i].l>=l&&g[i].r<=r&&g[i].pd==1){//如果pd为1代表里面的所有数都已经和lowbit一样
g[i].sum=g[i].sum*2%mod;//因为一样所以是两倍
g[i].lazy=g[i].lazy*2%mod;//懒标记也乘2
return ;
}
if(g[i].l==g[i].r){//先不直接处理整个区间,而是先把和lowbit不同的数逐渐处理成相同
g[i].sum=g[i].sum+lowbit(g[i].sum);
if(g[i].sum==lowbit(g[i].sum))g[i].pd=1;//一旦相同则标记
return ;
}
pushdown(i);
int mid=g[i].l+g[i].r>>1;
if(mid>=l)modify(i<<1,l,r);
if(mid<r)modify(i<<1|1,l,r);
pushup(i);
}
int query(int i,int l,int r){//区间求和板子
if(g[i].l>=l&&g[i].r<=r)return g[i].sum%mod;
pushdown(i);
int mid=g[i].l+g[i].r>>1;
int res=0;
if(l<=mid)res=(res+query(i<<1,l,r))%mod;
if(mid<r)res=(res+query(i<<1|1,l,r))%mod;
return res;
}
void solve () {
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
build(1,1,n);
cin>>m;
while(m--){
int op,l,r;
cin>>op>>l>>r;
if(op==1){
modify(1,l,r);
}
else{
cout<<query(1,l,r)%mod<<endl;
}
}
for(int i=1;i<=4*n;i++){
g[i]={0,0,0,0,0};
}
}
signed main () {
int T = 1;
std::ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin>>T;
while (T --) solve ();
return 0;
}