洛谷3707 [SDOI2017] 相关分析 【线段树】
分析:
化简一下就行了,注意一下平方和公式的运用以及精度的误差。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 const int maxn = 105000; 5 6 int n,m; 7 8 int x[maxn],y[maxn]; 9 10 struct node{ 11 int lazx1,lazx2,lazy1,lazy2; 12 double multi,sumx,sumy,sqr; 13 }T[maxn<<2]; 14 15 long long ump(int l,int r){ 16 return (1ll*r*(r+1)*(2*r+1)-1ll*(l-1)*l*(2*l-1))/6; 17 } 18 19 void fugai(int now,int tl,int tr,int s,int t){ 20 T[now].lazx2 = T[now].lazy2 = 0; 21 T[now].lazx1 = s; T[now].lazy1 = t; 22 T[now].sumx = 1ll*((s+tl)+(s+tr))*(tr-tl+1)/2; 23 T[now].sumy = 1ll*((t+tl)+(t+tr))*(tr-tl+1)/2; 24 T[now].sqr = 1ll*(tr-tl+1)*s*s+1ll*s*(tl+tr)*(tr-tl+1)+ump(tl,tr); 25 T[now].multi=1ll*(tr-tl+1)*s*t+1ll*(s+t)*(tl+tr)*(tr-tl+1)/2+ump(tl,tr); 26 } 27 28 void add(int now,int tl,int tr,int s,int t){ 29 T[now].lazx2+=s;T[now].lazy2 += t; 30 T[now].multi+=1ll*s*T[now].sumy+1ll*t*T[now].sumx+1ll*s*t*(tr-tl+1); 31 T[now].sqr +=1ll*s*s*(tr-tl+1)+2ll*s*T[now].sumx; 32 T[now].sumx += 1ll*s*(tr-tl+1); T[now].sumy += 1ll*t*(tr-tl+1); 33 } 34 35 void push_up(int now){ 36 T[now].multi = T[now<<1].multi+T[now<<1|1].multi; 37 T[now].sumx = T[now<<1].sumx+T[now<<1|1].sumx; 38 T[now].sumy = T[now<<1].sumy+T[now<<1|1].sumy; 39 T[now].sqr = T[now<<1].sqr+T[now<<1|1].sqr; 40 } 41 42 void push_down1(int now,int tl,int tr){ 43 int mid = (tl+tr)/2; 44 fugai(now<<1,tl,mid,T[now].lazx1,T[now].lazy1); 45 fugai(now<<1|1,mid+1,tr,T[now].lazx1,T[now].lazy1); 46 T[now].lazx1 = T[now].lazy1 = 123456; 47 } 48 49 void push_down2(int now,int tl,int tr){ 50 int mid = (tl+tr)/2; 51 add(now<<1,tl,mid,T[now].lazx2,T[now].lazy2); 52 add(now<<1|1,mid+1,tr,T[now].lazx2,T[now].lazy2); 53 T[now].lazx2 = T[now].lazy2 = 0; 54 } 55 56 void read(){ 57 scanf("%d%d",&n,&m); 58 for(int i=1;i<=n;i++)scanf("%d",&x[i]); 59 for(int i=1;i<=n;i++) scanf("%d",&y[i]); 60 } 61 62 node merge(node ai,node bi){ 63 return (node){0,0,0,0,ai.multi+bi.multi,ai.sumx+bi.sumx,ai.sumy+bi.sumy,ai.sqr+bi.sqr}; 64 } 65 66 void build_tree(int now,int l,int r){ 67 if(l == r){ 68 T[now].lazx1 = T[now].lazy1 = 123456; 69 T[now].multi = 1ll*x[l]*y[l]; 70 T[now].sumx = x[l];T[now].sumy = y[l]; 71 T[now].sqr = 1ll*x[l]*x[l]; 72 }else{ 73 int mid = (l+r)/2; 74 build_tree(now<<1,l,mid); 75 build_tree(now<<1|1,mid+1,r); 76 T[now].lazx1 = T[now].lazy1 = 123456; 77 push_up(now); 78 } 79 } 80 81 node Query(int now,int tl,int tr,int l,int r){ 82 if(tl >= l && tr <= r){return T[now];} 83 if(tl > r || tr < l){return (node){0,0,0,0,0,0,0,0};} 84 if(T[now].lazx1<=maxn||T[now].lazy1<=maxn) push_down1(now,tl,tr); 85 if(T[now].lazx2||T[now].lazy2) push_down2(now,tl,tr); 86 int mid = (tl+tr)/2; 87 node ans = merge(Query(now<<1,tl,mid,l,r),Query(now<<1|1,mid+1,tr,l,r)); 88 push_up(now); 89 return ans; 90 } 91 92 void Modify1(int now,int tl,int tr,int l,int r,int s,int t){ 93 if(tl >= l && tr <= r){ 94 add(now,tl,tr,s,t); 95 return; 96 } 97 if(tl > r || tr < l){return;} 98 if(T[now].lazx1<=maxn||T[now].lazy1<=maxn) push_down1(now,tl,tr); 99 if(T[now].lazx2||T[now].lazy2) push_down2(now,tl,tr); 100 int mid = (tl+tr)/2; 101 Modify1(now<<1,tl,mid,l,r,s,t); 102 Modify1(now<<1|1,mid+1,tr,l,r,s,t); 103 push_up(now); 104 } 105 106 void Modify2(int now,int tl,int tr,int l,int r,int s,int t){ 107 if(tl >= l && tr <= r){ 108 fugai(now,tl,tr,s,t); 109 return; 110 } 111 if(tl > r || tr < l){return;} 112 if(T[now].lazx1<=maxn||T[now].lazy1<=maxn) push_down1(now,tl,tr); 113 if(T[now].lazx2||T[now].lazy2) push_down2(now,tl,tr); 114 int mid = (tl+tr)/2; 115 Modify2(now<<1,tl,mid,l,r,s,t); 116 Modify2(now<<1|1,mid+1,tr,l,r,s,t); 117 push_up(now); 118 } 119 120 void work(){ 121 build_tree(1,1,n); 122 for(int i=1;i<=m;i++){ 123 int cas; scanf("%d",&cas); 124 if(cas == 1){ 125 int l,r; scanf("%d%d",&l,&r); 126 node forw = Query(1,1,n,l,r); 127 double pjx = 1.0*forw.sumx/(r-l+1),pjy = 1.0*forw.sumy/(r-l+1); 128 double res=forw.multi+pjx*pjy*(r-l+1)-pjx*forw.sumy-pjy*forw.sumx; 129 res /= 1.0*(forw.sqr+pjx*pjx*(r-l+1)-2.0*pjx*forw.sumx); 130 printf("%.10lf\n",res); 131 }else{ 132 if(cas == 2){ 133 int l,r,s,t; scanf("%d%d%d%d",&l,&r,&s,&t); 134 Modify1(1,1,n,l,r,s,t); 135 }else{ 136 int l,r,s,t; scanf("%d%d%d%d",&l,&r,&s,&t); 137 Modify2(1,1,n,l,r,s,t); 138 } 139 } 140 } 141 } 142 143 int main(){ 144 read(); 145 work(); 146 return 0; 147 }