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;
}
posted @ 2025-08-31 15:05  Rigel602458  阅读(3)  评论(0)    收藏  举报