1. 程式人生 > >水題-sdoi2017-相關分析

水題-sdoi2017-相關分析

線段樹.維護四個值:x,y,xy,x2
3操作拆分成一個賦值操作外加一個2操作就行了。預處理一下平方和之類的就好了。
注意幾個問題:
1.不要用long long(會爆long long),要用double.
2.最後是把2,3操作的lazy標記分開寫。處理3標記時,直接清空2標記.

貼個程式碼:

#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 105000
//#define LL long long
#define ls (p<<1)
#define rs (p<<1|1)
void _r(int& x,bool f=0) { char c=getchar(); while(c<'0'||c>'9') { f|=(c=='-'); c=getchar(); } for(x=0;c>='0'&&c<='9';c=getchar()) { x=(x<<1)+(x<<3)+c-'0'; } x=f?-x:x; return ; } double vx[MAXN<<2],vy[MAXN<<2
],vxx[MAXN<<2],vxy[MAXN<<2],tx[MAXN<<2],ty[MAXN<<2],ti[MAXN<<2],x_2[MAXN],x_1[MAXN]; int x[MAXN],y[MAXN]; int n,m; void merge(int p,int l,int r) { vx[p]=vx[l]+vx[r]; vy[p]=vy[l]+vy[r]; vxx[p]=vxx[l]+vxx[r]; vxy[p]=vxy[l]+vxy[r]; return ; } void build(int
p,int l,int r) { if(l==r) { vx[p]=x[l]; vy[p]=y[l]; vxx[p]=1ll*x[l]*x[l]; vxy[p]=1ll*x[l]*y[l]; return ; } int mid=(l+r)>>1; build(ls,l,mid); build(rs,mid+1,r); merge(p,ls,rs); return ; } void up1(int p,int l,int r) { vx[p]=vy[p]=x_1[r]-x_1[l-1]; vxx[p]=vxy[p]=x_2[r]-x_2[l-1]; ti[p]=1; tx[p]=ty[p]=0; return ; } void up2(int p,int l,int r,double dx,double dy) { tx[p]+=dx; ty[p]+=dy; vxy[p]+=vx[p]*dy+vy[p]*dx+dx*dy*1.0*(r-l+1); vxx[p]+=vx[p]*dx*2ll+dx*dx*1.0*(r-l+1); vx[p]+=dx*1.0*(r-l+1); vy[p]+=dy*1.0*(r-l+1); return ; } void push(int p,int l,int r) { int mid=(l+r)>>1; if(ti[p]) { up1(ls,l,mid); up1(rs,mid+1,r); ti[p]=0; } if(tx[p]||ty[p]) { up2(ls,l,mid,tx[p],ty[p]); up2(rs,mid+1,r,tx[p],ty[p]); tx[p]=ty[p]=0; } return ; } void add(int p,int l,int r,int x,int y,double dx,double dy) { if(l>=x&&r<=y) { up2(p,l,r,dx,dy); return ; } push(p,l,r); int mid=(l+r)>>1; if(x<=mid) { add(ls,l,mid,x,y,dx,dy); } if(y>mid) { add(rs,mid+1,r,x,y,dx,dy); } merge(p,ls,rs); return ; } void change(int p,int l,int r,int x,int y) { if(l>=x&&r<=y) { up1(p,l,r); return ; } push(p,l,r); int mid=(l+r)>>1; if(x<=mid) { change(ls,l,mid,x,y); } if(y>mid) { change(rs,mid+1,r,x,y); } merge(p,ls,rs); } struct node { double x,y,xx,xy; node(double a=0,double b=0,double c=0,double d=0) { x=a; y=b; xx=c; xy=d; } node operator + (node p) { return node(x+p.x,y+p.y,xx+p.xx,xy+p.xy); } }; node query(int p,int l,int r,int x,int y) { if(l>=x&&r<=y) { return node(vx[p],vy[p],vxx[p],vxy[p]); } push(p,l,r); int mid=(l+r)>>1; node t=node(0.0,0.0,0.0,0.0); if(x<=mid) { t=t+query(ls,l,mid,x,y); } if(y>mid) { t=t+query(rs,mid+1,r,x,y); } return t; } int main() { _r(n); _r(m); for(int i=1;i<=n;i++) { _r(x[i]); x_1[i]=x_1[i-1]+1.0*i; x_2[i]=x_2[i-1]+1.0*i*i; } for(int i=1;i<=n;i++) { _r(y[i]); } node p; build(1,1,n); for(int i=1,q,x,y,s,t;i<=m;i++) { _r(q); _r(x); _r(y); if(q==1) { p=query(1,1,n,x,y); printf("%.10lf\n",(p.xy-p.x*p.y/(y-x+1))/(p.xx-p.x*p.x/(y-x+1))); } if(q==2) { _r(s); _r(t); add(1,1,n,x,y,s,t); } if(q==3) { _r(s); _r(t); change(1,1,n,x,y); add(1,1,n,x,y,s,t); } } return 0; }