JZOJ 5943. 【NOIP2018模擬11.01】樹
阿新 • • 發佈:2018-12-19
題目
對於 100% 的資料,,$ k ≤ 2^30
題解
每個數多被減30次。 線段樹維護,這一段全部是0?全部是1?既有0又有1? 如果全是0,那麼直接return。 通過勢能分析,總複雜度為
程式碼
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define N 100010
#define LL long long
#define P(a) putchar(a)
#define mo 998244353
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
LL tr[N],tr2[N];
LL Tr[30][N<<2];
int i,j,k,l,r,n,m,q,cs,op;
int O,opx,opy,opl,opr,ans;
LL Ans,a1,A,w;
int a[N],_2[31],_22[31];
int read(){
int fh=0,rs=0;char ch=0;
while((ch<'0'||ch>'9')&&(ch^'-'))ch=getchar();
if(ch=='-')fh=1,ch=getchar();
while(ch>='0'&&ch<='9')rs=(rs<<3)+(rs<<1)+(ch^'0'),ch=getchar();
return fh?-rs:rs;
}
void write(int x){
if(x>9)write(x/10);
P(x%10+'0');
}
int lowbit (int x){return x&(-x);}
void add(int x,LL z){
for(;x<=n;x=x+lowbit(x))
tr[x]=tr[x]+z;
}
LL qry(int x){
LL rs=0;
for(;x;x=x-lowbit(x))rs=rs+tr[x];
return rs;
}
void add2(int x,LL z){
for(;x<=n;x=x+lowbit(x))
tr2[x]=(tr2[x]+z)%mo;
}
LL qry2(int x){
LL rs=0;
for(;x;x=x-lowbit(x))rs=(rs+tr2[x])%mo;
return rs;
}
void update(int ps){
if(Tr[opy][ps<<1]==1&&Tr[opy][(ps<<1)|1]==1){
Tr[opy][ps]=1;
}else
if(Tr[opy][ps<<1]==0&&Tr[opy][(ps<<1)|1]==0){
Tr[opy][ps]=0;
}else Tr[opy][ps]=2;
}
void chx(int ps,int l,int r){
if(Tr[opy][ps]==0)return;
if(opl<=l&&r<=opr&&Tr[opy][ps]==1){
int i;
fo(i,l,r){
add2(i,(mo-1ll*a[i]*a[i]%mo)%mo);
add(i,-_2[opy]);
a[i]=a[i]-_2[opy];
add2(i,1ll*a[i]*a[i]%mo);
}
Tr[opy][ps]=0;
return;
}
if(l==r)return;
int wz=(l+r)>>1;
if(opl<=wz)chx(ps<<1,l,wz);
if(opr>wz)chx((ps<<1)|1,wz+1,r);
update(ps);
}
void build(int ps,int l,int r){
if(l==r){
int i;
fo(i,0,29)if(_2[i]&a[l]){
Tr[i][ps]=1;
}
return;
}
int wz=(l+r)>>1;
build(ps<<1,l,wz);
build((ps<<1)|1,wz+1,r);
fo(opy,0,29)update(ps);
}
int main(){
O=1073741823;
_2[0]=1;_22[0]=1;
fo(i,1,30){
_2[i]=_2[i-1]<<1;
_22[i]=(1ll*_2[i]*_2[i])%mo;
}
n=read();
fo(i,1,n){
a[i]=read();
add(i,a[i]);
add2(i,(1ll*a[i]*a[i])%mo);
}
build(1,1,n);
fo(j,0,29){
opy=j;
fo(i,1,n)if(a[i]&_2[j]){
opx=i;
chx(1,1,n);
}
}
q=read();
fo(cs,1,q){
op=read();
if(op==1){
opl=read(),opr=read();k=read();
fo(opy,0,29)if(!(k&_2[opy])){
chx(1,1,n);
}
}else
if(op==2){
opl=read(),opr=read();
Ans=qry(opr)-qry(opl-1);
printf("%lld\n",Ans);
}else{
opl=read(),opr=read();
Ans=(qry2(opr)-qry2(opl-1)+mo)%mo;
Ans=(Ans*2*(opr-opl+1)%mo)%mo;
A=(qry(opr)-qry(opl-1)+mo)%mo;
A=(A*A%mo)*2%mo;
ans=(Ans+A)%mo;
write(ans),P('\n');
}
}
return 0;
}