P10511 方差
思路
数学题。
对于区间 \([l,r]\),设 \(m=r-l+1\),则:
\( \begin{aligned} m^2s^2&=m\sum\limits_{i=l}^{r}(a_i-\overline{a})^2\\ &=m\sum\limits_{i=l}^{r}(a_i^2-2a_i\overline{a}+\overline{a}^2)\\ &=m\left(\sum\limits_{i=l}^{r}a_i^2-2\sum\limits_{i=l}^{r}a_i\overline{a}+\sum\limits_{i=l}^{r}\overline{a}^2\right)\\ &=m\left(\sum\limits_{i=l}^{r}a_i^2-\frac{2}{m}\left(\sum\limits_{i=l}^{r}a_i\right)^2+\frac{1}{m}\left(\sum\limits_{i=l}^{r}a_i\right)^2\right)\\ &=m\sum\limits_{i=l}^{r}a_i^2-2\left(\sum\limits_{i=l}^{r}a_i\right)^2+\left(\sum\limits_{i=l}^{r}a_i\right)^2\\ &=m\sum\limits_{i=l}^{r}a_i^2-\left(\sum\limits_{i=l}^{r}a_i\right)^2. \end{aligned} \)
不难发现,维护区间和与区间平方和即可。
利用前缀和维护区间和与区间平方和。查询时,利用 upper_bound()
找到完全包含查询区间的区间,计算区间和与区间平方和,分别减去两边多余的部分,最后计算方差。
代码
取模使用 modint
。
特别地,l
数组与 r
数组应存储原始值。
#include<bits/stdc++.h>
#define int long long
#define TT 998244353
#define M(x) (modint){x}
#define maxm 200010
using namespace std;
int n,m,q,l[maxm],r[maxm];
struct modint{
int v;
bool operator<(const modint &b)const{return v<b.v;}
modint operator+(const modint &b)const{return (modint){(v+b.v)%TT};}
modint operator-(const modint &b)const{return (modint){((v-b.v)%TT+TT)%TT};}
modint operator*(const modint &b)const{return (modint){(v*b.v)%TT};}
}b[maxm],s1[maxm],s2[maxm],ans;
inline int read(){
int ret=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')ret=ret*10+(ch&15),ch=getchar();
return ret*f;
}
signed main(){
n=read(),m=read(),q=read();
for(int i=1;i<=m;i++)l[i]=read(),r[i]=read(),b[i].v=read()%TT;
for(int i=1;i<=m;i++){
s1[i]=s1[i-1]+b[i]*M((r[i]-l[i]+1)%TT);
s2[i]=s2[i-1]+b[i]*b[i]*M((r[i]-l[i]+1)%TT);
}
while(q--){
modint S1={0},S2={0};
int x=read(),y=read();
int L=upper_bound(l+1,l+m+1,x)-l-1;
int R=upper_bound(l+1,l+m+1,y)-l-1;
if(L<=R){
S1=S1+s1[R]-s1[L-1];
S2=S2+s2[R]-s2[L-1];
}
if(l[L]!=x){
S1=S1-b[L]*M((x-l[L])%TT);
S2=S2-b[L]*b[L]*M((x-l[L])%TT);
}
if(r[R]!=y){
S1=S1-b[R]*M((r[R]-y)%TT);
S2=S2-b[R]*b[R]*M((r[R]-y)%TT);
}
ans=M((y-x+1)%TT)*S2-S1*S1;
printf("%lld\n",ans.v);
}
return 0;
}