luogu3707 相关分析 (线段树)

把式子展开以后会发现,可以用线段树维护$x,y,x*y,x^2$分别的区间和

然后操作有区间加和区间修改

这个pushdown的时候,如果改和加的标记同时存在,那一定是先改再加,要不然加的标记已经被清掉了

所以在pushdown的时候,如果有改的标记,要把孩子的加的标记清掉

然后注意细节就行了(用*传数组 然后在函数里改了的话 它真的会改的 怎么就意识不到呢...)

  1 #include<bits/stdc++.h>
  2 #define pa pair<int,int>
  3 #define CLR(a,x) memset(a,x,sizeof(a))
  4 using namespace std;
  5 typedef long long ll;
  6 const int maxn=1e5+10,inf=1e9;
  7 
  8 inline ll rd(){
  9     ll x=0;char c=getchar();int neg=1;
 10     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
 11     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
 12     return x*neg;
 13 }
 14 
 15 struct Node{
 16     double x,y,xy,x2;
 17     int l,r;
 18     Node(double a=0,double b=0,double c=0,double d=0,int e=0,int f=0){
 19         x=a,y=b,xy=c,x2=d,l=e,r=f;
 20     }
 21 }tr[maxn*4];
 22 double laz[maxn*4][4];
 23 int ch[maxn*4][2],pct,X[maxn],Y[maxn];
 24 int N,M;
 25 
 26 Node operator + (Node a,Node b){
 27     Node p;
 28     p.l=a.l,p.r=b.r;
 29     p.x=a.x+b.x,p.y=a.y+b.y;
 30     p.xy=a.xy+b.xy,p.x2=a.x2+b.x2;
 31     return p;
 32 }
 33 
 34 inline void deal(Node &p,double *v){
 35     int r=p.r,l=p.l;
 36     if(v[2]!=-inf){
 37         p.x=p.y=1ll*(p.r+p.l)*(p.r-p.l+1)/2;
 38         p.xy=p.x2=(1ll*r*(r+1)*(2*r+1))/6-(1ll*(l-1)*l*(2*l-1))/6;
 39         v[0]+=v[2],v[1]+=v[3];
 40     }
 41     
 42     p.x2+=(p.r-p.l+1)*v[0]*v[0]+2*v[0]*p.x;
 43     p.xy+=v[0]*p.y+v[1]*p.x+(p.r-p.l+1)*v[0]*v[1];
 44     p.x+=(p.r-p.l+1)*v[0],p.y+=(p.r-p.l+1)*v[1];
 45     if(v[2]!=-inf) v[0]-=v[2],v[1]-=v[3];
 46 }
 47 
 48 inline void pushdown(int p){
 49     // return;
 50     if(!ch[p][0]) return;
 51     if(laz[p][0]==0&&laz[p][1]==0&&laz[p][2]==-inf) return;
 52     int a=ch[p][0],b=ch[p][1];
 53     if(laz[p][2]!=-inf){
 54         laz[a][0]=laz[a][1]=laz[b][0]=laz[b][1]=0;
 55         laz[a][2]=laz[p][2],laz[a][3]=laz[p][3];
 56         laz[b][2]=laz[p][2],laz[b][3]=laz[p][3];
 57     }
 58     laz[a][0]+=laz[p][0],laz[a][1]+=laz[p][1];
 59     laz[b][0]+=laz[p][0],laz[b][1]+=laz[p][1];
 60     
 61     deal(tr[a],laz[p]);
 62     deal(tr[b],laz[p]);
 63     laz[p][0]=laz[p][1]=0,laz[p][2]=laz[p][3]=-inf;
 64 }
 65 
 66 void build(int &p,int l,int r){
 67     p=++pct;
 68     laz[p][2]=laz[p][3]=-inf;
 69     if(l==r){
 70         tr[p]=Node(X[l],Y[l],1ll*X[l]*Y[l],1ll*X[l]*X[l],l,r);
 71     }else{
 72         int m=l+r>>1;
 73         build(ch[p][0],l,m);
 74         build(ch[p][1],m+1,r);
 75         tr[p]=tr[ch[p][0]]+tr[ch[p][1]];
 76     }
 77 }
 78 
 79 void query(int p,int l,int r,int x,int y,Node &q){
 80     pushdown(p);
 81     if(x<=l&&r<=y){
 82         if(!q.l) q=tr[p];
 83         else q=q+tr[p];
 84     }else{
 85         int m=l+r>>1;
 86         if(x<=m) query(ch[p][0],l,m,x,y,q);
 87         if(y>=m+1) query(ch[p][1],m+1,r,x,y,q);
 88     }
 89 }
 90 
 91 void add(int p,int l,int r,int x,int y,int s,int t){
 92     pushdown(p);
 93     if(x<=l&&r<=y){
 94         double v[5];
 95         v[0]=s,v[1]=t;v[2]=v[3]=-inf;
 96         deal(tr[p],v);
 97         laz[p][0]+=s,laz[p][1]+=t;
 98         pushdown(p);
 99     }else{
100         int m=l+r>>1;
101         if(x<=m) add(ch[p][0],l,m,x,y,s,t);
102         if(y>=m+1) add(ch[p][1],m+1,r,x,y,s,t);
103         tr[p]=tr[ch[p][0]]+tr[ch[p][1]];
104     }
105 }
106 
107 void change(int p,int l,int r,int x,int y,int s,int t){
108     if(x<=l&&r<=y){
109         double v[5];
110         v[0]=v[1]=0,v[2]=s,v[3]=t;
111         deal(tr[p],v);
112         laz[p][0]=laz[p][1]=0,laz[p][2]=s,laz[p][3]=t;
113         pushdown(p);
114     }else{
115         pushdown(p);    
116         int m=l+r>>1;
117         if(x<=m) change(ch[p][0],l,m,x,y,s,t);
118         if(y>=m+1) change(ch[p][1],m+1,r,x,y,s,t);
119         tr[p]=tr[ch[p][0]]+tr[ch[p][1]];
120     }
121 }
122 
123 int main(){
124     int i,j,k;
125     N=rd(),M=rd();
126     for(i=1;i<=N;i++) X[i]=rd();
127     for(i=1;i<=N;i++) Y[i]=rd();
128     build(i,1,N);
129     for(i=1;i<=M;i++){
130         int a=rd(),b=rd(),c=rd();
131         if(a==1){
132             Node p;
133             query(1,1,N,b,c,p);
134             double xb=p.x/(c-b+1),yb=p.y/(c-b+1);
135             double ans=0;
136             ans=p.xy-xb*p.y-yb*p.x+xb*yb*(c-b+1);
137             ans/=p.x2-2*xb*p.x+xb*xb*(c-b+1);
138             printf("%.10lf\n",ans);
139         }else{
140             int d=rd(),e=rd();
141             if(a==2){
142                 add(1,1,N,b,c,d,e);
143             }else if(a==3){
144                 change(1,1,N,b,c,d,e);
145             }
146         }
147     }
148     return 0;
149 }

 

posted @ 2018-10-15 21:26  Ressed  阅读(159)  评论(0编辑  收藏  举报