线段树求调
  • 板块灌水区
  • 楼主OrientDragon
  • 当前回复0
  • 已保存回复0
  • 发布时间2024/12/14 16:33
  • 上次更新2024/12/14 19:30:35
查看原帖
线段树求调
1173109
OrientDragon楼主2024/12/14 16:33

P1471

#include<bits/stdc++.h>
using namespace std;

const int N=100005;

int n,m,opt,x,y;
double k,a[N];

struct SegTree{
	int l,r;
	double sum,sqrsum;
	bool lazy;
	#define l(x) tree[x].l
	#define r(x) tree[x].r
	#define sum(x) tree[x].sum
	#define sqr(x) tree[x].sqrsum
	#define lazy(x) tree[x].lazy
	SegTree(){l=r=sum=lazy=0;}
}tree[N<<3];

void build(int x,int l,int r){
	if(l>r)return;
	if(l==r){
		l(x)=r(x)=l;
		sum(x)=a[l];
		sqr(x)=a[l]*a[l];
		return;
	}
	int mid=l+r>>1;
	build(x<<1,l,mid);
	build(x<<1|1,mid+1,r);
	l(x)=l,r(x)=r;
	sum(x)=sum(x<<1)+sum(x<<1|1);
	sqr(x)=sqr(x<<1)+sqr(x<<1|1);
}

void pushdown(int x){
	if(!lazy(x))return;
	lazy(x<<1)+=lazy(x);
	lazy(x<<1|1)+=lazy(x);
	sqr(x<<1)+=2*lazy(x)*sum(x<<1)+(r(x<<1)-l(x<<1)+1)*lazy(x)*lazy(x); 
	sqr(x<<1|1)+=2*lazy(x)*sum(x<<1|1)+(r(x<<1|1)-l(x<<1|1)+1)*lazy(x)*lazy(x);
	sum(x<<1)+=(r(x<<1)-l(x<<1)+1)*lazy(x);
	sum(x<<1|1)+=(r(x<<1|1)-l(x<<1|1)+1)*lazy(x);
	lazy(x)=0;
}

void modify(int x,int askl,int askr,double val){
	int l=l(x),r=r(x);
	if(askl<=l&&r<=askr){
		lazy(x)+=val;
		sqr(x)+=2*val*sum(x)+(r-l+1)*val*val;
		sum(x)+=(r-l+1)*val;
		return;
	}
	pushdown(x);
	int mid=l+r>>1;
	if(askl<=mid)modify(x<<1,askl,askr,val);
	if(askr>mid)modify(x<<1|1,askl,askr,val);
	sum(x)=sum(x<<1)+sum(x<<1|1);
	sqr(x)=sqr(x<<1)+sqr(x<<1|1);
}

double SUM(int x,int askl,int askr){
	int l=l(x),r=r(x);
	pushdown(x);
	if(askl<=l&&r<=askr)return sum(x);
	int mid=l+r>>1;
	double ret=0;
	if(askl<=mid)ret+=SUM(x<<1,askl,askr);
	if(askr>mid)ret+=SUM(x<<1|1,askl,askr);
	return ret;
}

double SQR(int x,int askl,int askr){
	int l=l(x),r=r(x);
	pushdown(x);
	if(askl<=l&&r<=askr)return sqr(x);
	int mid=l+r>>1;
	double ret=0;
	if(askl<=mid)ret+=SQR(x<<1,askl,askr);
	if(askr>mid)ret+=SQR(x<<1|1,askl,askr);
	return ret;
}

signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cout<<fixed<<setprecision(4);
	cin>>n>>m;
	for(int i=1;i<=n;i++)cin>>a[i];
	build(1,1,n);
	while(m--){
		cin>>opt>>x>>y;
		if(opt==1)cin>>k,modify(1,x,y,k);
		else if(opt==2)cout<<(double)SUM(1,x,y)/(y-x+1.0)<<endl;
		else{
			double var=(double)SQR(1,x,y)/(y-x+1.0),aver=(double)SUM(1,x,y)/(y-x+1.0);
			cout<<var-aver*aver<<endl;
		}
	}
}
2024/12/14 16:33
加载中...