每个节点被经过的概率即为该区间和/总区间和。那么所需要计算的东西就是每个节点的平方和了。修改对于某个节点的影响是使其增加2sum·l·x+l2x2。那么考虑对子树的影响,其中Σl2是定值,修改后Σsum·l会增加Σl2x。维护一下就好。
懒得纠结爆long long的问题了,被卡90算了。
// luogu-judger-enable-o2 // luogu-judger-enable-o2 #include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } #define N 100010 #define P 998244353 #define ll long long int n,m,a[N],L[N<<2],R[N<<2],sum[N<<2],ssqr[N<<2],ssum[N<<2],slen[N<<2],lazy[N<<2]; int ksm(int a,int k) { int s=1; for (;k;k>>=1,a=1ll*a*a%P) if (k&1) s=1ll*s*a%P; return s; } int inv(int a){return ksm(a,P-2);} void inc(int &x,int y){x+=y;if (x>=P) x-=P;} void up(int k) { sum[k]=(sum[k<<1]+sum[k<<1|1])%P; ssum[k]=((ssum[k<<1]+ssum[k<<1|1])%P+1ll*sum[k]*(R[k]-L[k]+1)%P)%P; ssqr[k]=((ssqr[k<<1]+ssqr[k<<1|1])%P+1ll*sum[k]*sum[k]%P)%P; slen[k]=((slen[k<<1]+slen[k<<1|1])%P+1ll*(R[k]-L[k]+1)*(R[k]-L[k]+1)%P)%P; } void build(int k,int l,int r) { L[k]=l,R[k]=r; if (l==r) {ssum[k]=sum[k]=a[l];ssqr[k]=1ll*a[l]*a[l]%P;slen[k]=1;return;} int mid=l+r>>1; build(k<<1,l,mid); build(k<<1|1,mid+1,r); up(k); } void work(int k,int x) { inc(sum[k],1ll*x*(R[k]-L[k]+1)%P); inc(ssqr[k],(1ll*x*x%P*slen[k]%P+2ll*x%P*ssum[k]%P)%P); inc(ssum[k],1ll*slen[k]*x%P); inc(lazy[k],x); } void down(int k) { work(k<<1,lazy[k]),work(k<<1|1,lazy[k]); lazy[k]=0; } void modify(int k,int l,int r,int x) { if (L[k]==l&&R[k]==r) {work(k,x);return;} if (lazy[k]) down(k); int mid=L[k]+R[k]>>1; if (r<=mid) modify(k<<1,l,r,x); else if (l>mid) modify(k<<1|1,l,r,x); else modify(k<<1,l,mid,x),modify(k<<1|1,mid+1,r,x); up(k); } int main() { #ifndef ONLINE_JUDGE freopen("d.in","r",stdin); freopen("d.out","w",stdout); const char LL[]="%I64d "; #else const char LL[]="%lld "; #endif n=read(),m=read(); for (int i=1;i<=n;i++) a[i]=read(); build(1,1,n); while (m--) { int op=read(); if (op==1) { int x=read(),y=read(),z=read(); modify(1,x,y,z); } else printf("%d ",1ll*ssqr[1]*inv(sum[1])%P); } return 0; }