线段树 WA求助
  • 板块P1471 方差
  • 楼主IGJHL
  • 当前回复2
  • 已保存回复2
  • 发布时间2023/7/17 13:20
  • 上次更新2023/11/3 09:21:36
查看原帖
线段树 WA求助
357463
IGJHL楼主2023/7/17 13:20

rt,样例都是错的...求调

#include <iostream>
#include <cstdio>
using namespace std;

const int N = 1e5 + 5;

struct node{
	double sum, pw, tag;//pw为区间平方和 
	node() {
		sum = pw = tag = 0;
	}
} tr[N];
int n, m, a[N];
void pushup(node &u, node &l, node &r) {
	u.sum = l.sum + r.sum;
	u.pw = l.pw + r.pw;
} 
void pushup(int u) {
	pushup(tr[u], tr[u << 1], tr[u << 1 | 1]);
}
void build(int x, int l, int r) {
	if (l == r) {
		tr[l].sum = a[l], tr[l].pw = a[l] * a[l];
		return ; 
	}
	int mid = l + r >> 1;
	build(l << 1, l, mid), build(l << 1 | 1, mid + 1, r);
	pushup(x);
} 
void pushdown(int x, int l, int r) {
	int ls = x << 1, rs = ls | 1, mid = l + r >> 1;
	//标记下放左孩子 
	tr[ls].pw = tr[ls].pw + tr[x].tag * tr[ls].sum + (mid - l + 1) * tr[x].tag * tr[x].tag;
	tr[ls].sum = tr[ls].sum + tr[x].tag * (mid - l + 1), tr[ls].tag += tr[x].tag; 
	//标记下放右孩子 
	tr[rs].pw = tr[rs].pw + tr[x].tag * tr[rs].sum + (r - mid) * tr[x].tag * tr[x].tag;
	tr[rs].sum = tr[rs].sum + tr[x].tag * (r - mid), tr[rs].tag += tr[x].tag; 
	//标记下放完了,清零 
	tr[x].tag = 0;
}
void modify(int x, int l, int r, int ll, int rr, double k) {//给区间[ll,rr]加上k 
	if (l == ll && r == rr) {//找到修改区间了 
		tr[x].pw = tr[x].pw + 2 * k * tr[x].sum + k * k * (r - l + 1);
		tr[x].sum = tr[x].sum + k * (r - l + 1), tr[x].tag += k;
		return ;
	}
	int mid = l + r >> 1;
	if (tr[x].tag != 0)
		pushdown(x, l, r);
	if (ll > mid)//要修改的区间全在右孩子上 
		modify(x << 1 | 1, mid + 1, r, ll, rr, k);
	else if (rr <= mid)//要修改的区间全在左孩子上 
		modify(x << 1, l, mid, ll, rr, k);
	else//修改区间横跨左右孩子 
		modify(x << 1, l, mid, ll, mid, k), modify(x << 1 | 1, mid + 1, r, mid + 1, rr, k);
	pushup(x);//算完孩子,更新自己 
}
double query1(int x, int l, int r, int ll, int rr) {//返回[ll, rr]区间和 
	if (l == ll && r == rr)
		return tr[x].sum;
	int mid = l + r >> 1;
	if (tr[x].tag != 0)
		pushdown(x, l, r);
	if (ll > mid)//答案在右孩子
		return query1(x << 1 | 1, mid + 1, r, ll, rr);
	else if (rr <= mid)//答案在左孩子
		return query1(x << 1, l, mid, ll, rr);
	else//答案横跨左右孩子 
		return (query1(x << 1, l, mid, ll, mid) + query1(x << 1 | 1, mid + 1, r, mid + 1, rr));
}
double query2(int x, int l, int r, int ll, int rr) {//返回[ll, rr]区间平方和 
	if (l == ll && r == rr)
		return tr[x].pw;
	int mid = l + r >> 1;
	if (tr[x].tag != 0)
		pushdown(x, l, r);
	if (ll > mid)//答案在右孩子
		return query2(x << 1 | 1, mid + 1, r, ll, rr);
	else if (rr <= mid)//答案在左孩子
		return query2(x << 1, l, mid, ll, rr);
	else//答案横跨左右孩子 
		return (query2(x << 1, l, mid, ll, mid) + query2(x << 1 | 1, mid + 1, r, mid + 1, rr));
}

signed main() {
	cin >> n >> m;
	for (int i = 1; i <= n; ++ i)
		cin >> a[i];
	build(1, 1, n);
	while (m --) {
		int op, x, y; double k;
		cin >> op;
		if (op == 1) {
			cin >> x >> y >> k;
			modify(1, 1, n, x, y, k);
		}
		if (op == 2) {
			cin >> x >> y;
			printf("%.4lf\n", 1.0 * query1(1, 1, n, x, y) / (y - x + 1));
		}
		if (op == 3) {
			cin >> x >> y;
			double ans1 = query1(1, 1, n, x, y) * 1.0 / (y - x + 1), ans2 = query2(1, 1, n, x, y);
			printf("%.4lf\n", ans2 * 1.0 / (y - x + 1) - 1.0 * ans1 * ans1);
		}
	}
	
	return 0;
}
2023/7/17 13:20
加载中...