洛谷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 }

猜你喜欢

转载自www.cnblogs.com/Menhera/p/9148143.html