1. 程式人生 > >JZOJ 5943. 【NOIP2018模擬11.01】樹

JZOJ 5943. 【NOIP2018模擬11.01】樹

題目

在這裡插入圖片描述 對於 100% 的資料,n,q105n, q ≤ 10^5,ai109,ai ≤ 10^9,$ k ≤ 2^30,1lrn., 1 ≤ l ≤ r ≤ n.

題解

每個數多被減30次。 線段樹維護,這一段全部是0?全部是1?既有0又有1? 如果全是0,那麼直接return。 通過勢能分析,總複雜度為O(nlog2(n))O(n\ log^2(n))

程式碼

#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; }