C39 线段树+数学 P5142 区间方差
视频链接:225 线段树+数学 P5142 区间方差_哔哩哔哩_bilibili
#include<cstdio> using namespace std; typedef long long LL; const int N=100005,mod=1e9+7; #define ls u<<1 #define rs u<<1|1 #define sqr(x) ((LL)(x)*(x)%mod) int n,m,a[N]; int L[N<<2],R[N<<2],s1[N<<2],s2[N<<2]; //s1:区间和, s2:区间平方和 int qpow(int a){ //快速幂 int s=1, b=mod-2; while(b){ if(b&1) s=(LL)s*a%mod; a=(LL)a*a%mod; b>>=1; } return s; } void pushup(int u){ //上传 s1[u]=(s1[ls]+s1[rs])%mod; s2[u]=(s2[ls]+s2[rs])%mod; } void build(int u,int l,int r){ //建树 L[u]=l;R[u]=r; s1[u]=a[l];s2[u]=sqr(a[l]); if(l==r) return; int m=(l+r)>>1; build(ls,l,m); build(rs,m+1,r); pushup(u); } void change(int u,int k,int v){ //点修 if(L[u]==R[u]){ s1[u]=v; s2[u]=sqr(v); return; } int m=(L[u]+R[u])>>1; if(k<=m) change(ls,k,v); else change(rs,k,v); pushup(u); } int q1(int u,int x,int y){ //区间和 if(x<=L[u] && R[u]<=y) return s1[u]; int m=(L[u]+R[u])>>1; if(y<=m) return q1(ls,x,y); if(x>m) return q1(rs,x,y); return (q1(ls,x,m)+q1(rs,m+1,y))%mod; } int q2(int u,int x,int y){ //区间平方和 if(x<=L[u] && R[u]<=y) return s2[u]; int m=(L[u]+R[u])>>1; if(y<=m) return q2(ls,x,y); if(x>m) return q2(rs,x,y); return (q2(ls,x,m)+q2(rs,m+1,y))%mod; } int main(){ scanf("%d%d",&n,&m); for(int i=1; i<=n; ++i) scanf("%d",&a[i]); build(1,1,n); int op,x,y,s1,s2,inv,ave,ans; while(m--){ scanf("%d%d%d",&op,&x,&y); if(op==1) change(1,x,y); else{ s1=q1(1,x,y); //区间和 s2=q2(1,x,y); //区间平方和 inv=qpow(y-x+1); //区间长度的逆元 ave=(LL)s1*inv%mod; //区间算术平均数 ans=(LL)s2*inv%mod-(LL)ave*ave%mod; ans=(ans%mod+mod)%mod; printf("%d\n",ans); } } return 0; }
#include<cstdio> using namespace std; typedef long long LL; const int N=100005,mod=1e9+7; #define ls u<<1 #define rs u<<1|1 #define sqr(x) ((LL)(x)*(x)%mod) int n,m,a[N]; int L[N<<2],R[N<<2],s1[N<<2],s2[N<<2]; //s1:区间和, s2:区间平方和 int qpow(int a){ //快速幂 int s=1, b=mod-2; while(b){ if(b&1) s=(LL)s*a%mod; a=(LL)a*a%mod; b>>=1; } return s; } void pushup(int u){ //上传 s1[u]=(s1[ls]+s1[rs])%mod; s2[u]=(s2[ls]+s2[rs])%mod; } void build(int u,int l,int r){ //建树 L[u]=l;R[u]=r; s1[u]=a[l];s2[u]=sqr(a[l]); if(l==r) return; int m=(l+r)>>1; build(ls,l,m); build(rs,m+1,r); pushup(u); } void change(int u,int k,int v){ //点修 if(L[u]==R[u]){ s1[u]=v; s2[u]=sqr(v); return; } int m=(L[u]+R[u])>>1; if(k<=m) change(ls,k,v); else change(rs,k,v); pushup(u); } int q1(int u,int x,int y){ //区间和 if(x<=L[u] && R[u]<=y) return s1[u]; int m=(L[u]+R[u])>>1; int res=0; if(x<=m) res=q1(ls,x,y); if(y>m) res=(res+q1(rs,x,y))%mod; return res; } int q2(int u,int x,int y){ //区间平方和 if(x<=L[u] && R[u]<=y) return s2[u]; int m=(L[u]+R[u])>>1; int res=0; if(x<=m) res=q2(ls,x,y); if(y>m) res=(res+q2(rs,x,y))%mod; return res; } int main(){ scanf("%d%d",&n,&m); for(int i=1; i<=n; ++i) scanf("%d",&a[i]); build(1,1,n); int op,x,y,s1,s2,inv,ave,ans; while(m--){ scanf("%d%d%d",&op,&x,&y); if(op==1) change(1,x,y); else{ s1=q1(1,x,y); //区间和 s2=q2(1,x,y); //区间平方和 inv=qpow(y-x+1); //区间长度的逆元 ave=(LL)s1*inv%mod; //区间算术平均数 ans=(LL)s2*inv%mod-(LL)ave*ave%mod; ans=(ans%mod+mod)%mod; printf("%d\n",ans); } } return 0; }
#include <cstdio> using namespace std; typedef long long LL; const int N=100005,mod=1e9+7; #define ls u<<1 #define rs u<<1|1 #define sqr(x) ((LL)(x)*(x)%mod) int n,m,a[N]; struct tree{ int l,r; int s1,s2; //区间和,区间平方和 }tr[N<<2]; int qpow(int a){ //快速幂 int s=1, b=mod-2; while(b){ if(b&1) s=(LL)s*a%mod; a=(LL)a*a%mod; b>>=1; } return s; } void pushup(int u){ //上传 tr[u].s1=(tr[ls].s1+tr[rs].s1)%mod; tr[u].s2=(tr[ls].s2+tr[rs].s2)%mod; } void build(int u,int l,int r){ //建树 tr[u]={l,r,a[l],sqr(a[l])}; if(l==r) return; int m=(l+r)>>1; build(ls,l,m); build(rs,m+1,r); pushup(u); } void change(int u,int k,int v){ //点修 if(tr[u].l==tr[u].r){ tr[u].s1=v; tr[u].s2=sqr(v); return; } int m=(tr[u].l+tr[u].r)>>1; if(k<=m) change(ls,k,v); else change(rs,k,v); pushup(u); } int q1(int u,int x,int y){ //区间和 if(x<=tr[u].l&&tr[u].r<=y)return tr[u].s1; int m=(tr[u].l+tr[u].r)>>1; if(y<=m) return q1(ls,x,y); if(x>m) return q1(rs,x,y); return (q1(ls,x,m)+q1(rs,m+1,y))%mod; } int q2(int u,int x,int y){ //区间平方和 if(x<=tr[u].l&&tr[u].r<=y)return tr[u].s2; int m=(tr[u].l+tr[u].r)>>1; if(y<=m) return q2(ls,x,y); if(x>m) return q2(rs,x,y); return (q2(ls,x,m)+q2(rs,m+1,y))%mod; } int main(){ scanf("%d%d",&n,&m); for(int i=1; i<=n; ++i) scanf("%d",&a[i]); build(1,1,n); int op,x,y,s1,s2,inv,ave,ans; while(m--){ scanf("%d%d%d",&op,&x,&y); if(op==1) change(1,x,y); else{ s1=q1(1,x,y); //区间和 s2=q2(1,x,y); //区间平方和 inv=qpow(y-x+1); //区间长度的逆元 ave=(LL)s1*inv%mod; //区间算术平均数 ans=(LL)s2*inv%mod-(LL)ave*ave%mod; ans=(ans%mod+mod)%mod; printf("%d\n",ans); } } return 0; }
分类:
C 数据结构
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!