40pts线段树蒟蒻求调
  • 板块P1471 方差
  • 楼主ZHR100102
  • 当前回复0
  • 已保存回复0
  • 发布时间2024/7/8 16:23
  • 上次更新2024/7/8 17:26:16
查看原帖
40pts线段树蒟蒻求调
947153
ZHR100102楼主2024/7/8 16:23

WA on #1,2,3,4,9,10
第一颗线段树维护区间和,第二颗线段树维护平方和。

#include <bits/stdc++.h>
#define lc (p<<1)
#define rc ((p<<1)|1)
using namespace std;
const int N=100005;
double a[N];
struct node{
	int l,r;
	double sum=0,tag=0;
}tr[3][4*N];//1:sum 2:sqr
void pushup1(int p)
{
	tr[1][p].sum=tr[1][lc].sum+tr[1][rc].sum;
}
void pushdown1(int p)
{
	if(tr[1][p].tag!=0)
	{
		tr[1][lc].sum+=(tr[1][lc].r-tr[1][lc].l+1)*tr[1][p].tag;
		tr[1][lc].tag+=tr[1][p].tag;
		tr[1][rc].sum+=(tr[1][rc].r-tr[1][rc].l+1)*tr[1][p].tag;
		tr[1][rc].tag+=tr[1][p].tag;
	}
	tr[1][p].tag=0;
}
void build1(int p,int ln,int rn)
{
	tr[1][p].l=ln,tr[1][p].r=rn,tr[1][p].sum=a[ln],tr[1][p].tag=0;
	if(ln==rn)return;
	int mid=(ln+rn)>>1;
	build1(lc,ln,mid);
	build1(rc,mid+1,rn);
	pushup1(p);
}
double query1(int p,int ln,int rn)
{
	if(tr[1][p].l>=ln&&tr[1][p].r<=rn)return tr[1][p].sum;
	pushdown1(p);
	int mid=(tr[1][p].l+tr[1][p].r)>>1;
	double nsum=0;
	if(ln<=mid)nsum+=query1(lc,ln,rn);
	if(rn>=mid+1)nsum+=query1(rc,ln,rn);
	return nsum;
}
void update1(int p,int ln,int rn,double k)
{
	if(tr[1][p].l>=ln&&tr[1][p].r<=rn)
	{
		tr[1][p].sum+=(tr[1][p].r-tr[1][p].l+1)*k;
		tr[1][p].tag+=k;
		return;
	}
	pushdown1(p);
	int mid=(tr[1][p].l+tr[1][p].r)>>1;
	if(ln<=mid)update1(lc,ln,rn,k);
	if(rn>=mid+1)update1(rc,ln,rn,k);
	pushup1(p);
}
void pushup2(int p)
{
	tr[2][p].sum=0;
	if(lc<4*N)tr[2][p].sum+=tr[2][lc].sum;
	if(rc<4*N)tr[2][p].sum+=tr[2][rc].sum;
}
void pushdown2(int p)
{
	if(tr[2][p].tag!=0)
	{
		if(lc<4*N)
		{
			tr[2][lc].tag+=tr[2][p].tag;
			tr[2][lc].sum+=(tr[2][lc].r-tr[2][lc].l+1)*tr[2][p].tag*tr[2][p].tag+2*tr[2][p].tag*query1(1,tr[2][lc].l,tr[2][lc].r);
		}
		if(rc<4*N)
		{
			tr[2][rc].tag+=tr[2][p].tag;
			tr[2][rc].sum+=(tr[2][rc].r-tr[2][rc].l+1)*tr[2][p].tag*tr[2][p].tag+2*tr[2][p].tag*query1(1,tr[2][rc].l,tr[2][rc].r);
		}		
	}
	tr[2][p].tag=0;
}
void build2(int p,int ln,int rn)
{
	tr[2][p].l=ln,tr[2][p].r=rn,tr[2][p].sum=a[ln]*a[ln],tr[2][p].tag=0;
	if(ln==rn)return;
	int mid=(ln+rn)>>1;
	build2(lc,ln,mid);
	build2(rc,mid+1,rn);
	pushup2(p);
}
double query2(int p,int ln,int rn)
{
	if(tr[2][p].l>=ln&&tr[2][p].r<=rn)return tr[2][p].sum;
	pushdown2(p);
	int mid=(tr[2][p].l+tr[2][p].r)>>1;
	double nsum=0;
	if(ln<=mid)nsum+=query2(lc,ln,rn);
	if(rn>=mid+1)nsum+=query2(rc,ln,rn);
	return nsum;
}
void update2(int p,int ln,int rn,double k)
{
	pushdown2(p);
	if(tr[2][p].l>=ln&&tr[2][p].r<=rn)
	{
		tr[2][p].tag+=k;
		tr[2][p].sum+=(tr[2][p].r-tr[2][p].l+1)*k*k+2*k*query1(1,tr[2][p].l,tr[2][p].r);
		return;
	}
	int mid=(tr[2][p].l+tr[2][p].r)>>1;
	if(ln<=mid)update2(lc,ln,rn,k);
	if(rn>=mid+1)update2(rc,ln,rn,k);
	pushup2(p);
}
int n,m;
int main()
{
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;i++)scanf("%lf",&a[i]);
	build1(1,1,n);
	build2(1,1,n);
	while(m--)
	{
		int op;
		int x,y;
		double k;
		scanf("%d",&op);
		if(op==1)
		{
			scanf("%d %d %lf",&x,&y,&k);
			update2(1,x,y,k);
			update1(1,x,y,k);
		}
		else if (op==2)
		{
			scanf("%d %d",&x,&y);
			printf("%.4lf\n",query1(1,x,y)*1.0/(y-x+1));
		}
		else
		{
			scanf("%d %d",&x,&y);
			double sum=query1(1,x,y);
			double aver=sum*1.0/(y-x+1);
			printf("%.4lf\n",(query2(1,x,y)+aver*aver*(y-x+1)-2*aver*sum)*1.0/(y-x+1));			
		}
	}
	return 0;
}
2024/7/8 16:23
加载中...