记录编号 601682 评测结果 AAAAAAAAAA
题目名称 2232.方差 最终得分 100
用户昵称 GravatarLikableP 是否通过 通过
代码语言 C++ 运行时间 1.357 s
提交时间 2025-06-27 11:39:49 内存使用 6.40 MiB
显示代码纯文本
#include <cstdio>

const int MAXN = 1e5 + 10;

struct SegmentTree {
  struct NODE {
    double sum;
    double sqsum;
    double lazy;
  } node[MAXN << 2];

#define ls(root) root << 1
#define rs(root) root << 1 | 1
  void PushUp(int root) {
    node[root].sum = node[ls(root)].sum + node[rs(root)].sum;
    node[root].sqsum = node[ls(root)].sqsum + node[rs(root)].sqsum;
  }

  void PushDown(int root, int lt, int rt) {
    if (node[root].lazy) {
      double lazy = node[root].lazy;
      int mid = lt + ((rt - lt) >> 1);
      node[ls(root)].sqsum += 2 * lazy * node[ls(root)].sum + (mid - lt + 1) * lazy * lazy;
      node[ls(root)].sum += (mid - lt + 1) * lazy;
      node[ls(root)].lazy += lazy;
      node[rs(root)].sqsum += 2 * lazy * node[rs(root)].sum + (rt - mid) * lazy * lazy;
      node[rs(root)].sum += (rt - mid) * lazy;
      node[rs(root)].lazy += lazy;
      node[root].lazy = 0;
    }
  }

  void Build(int root, int lt, int rt, double arr[]) {
    if (lt == rt) {
      return (void) (node[root] = {arr[lt], arr[lt] * arr[lt], 0});
    }
    int mid = lt + ((rt - lt) >> 1);
    Build(ls(root), lt, mid, arr);
    Build(rs(root), mid + 1, rt, arr);
    PushUp(root);
  }

  void AddSeq(int root, int lt, int rt, int lq, int rq, double val) {
    if (lt == lq && rt == rq) {
      node[root].sqsum += 2 * val * node[root].sum + (rq - lq + 1) * val * val;
      node[root].sum += val * (rq - lq + 1);
      node[root].lazy += val;
      return;
    }
    PushDown(root, lt, rt);
    int mid = lt + ((rt - lt) >> 1);
    if (rq <= mid) {
      AddSeq(ls(root), lt, mid, lq, rq, val);
    } else if (lq > mid) {
      AddSeq(rs(root), mid + 1, rt, lq, rq, val);
    } else {
      AddSeq(ls(root), lt, mid, lq, mid, val);
      AddSeq(rs(root), mid + 1, rt, mid + 1, rq, val);
    }
    PushUp(root);
  }

  double GetSum(int root, int lt, int rt, int lq, int rq) {
    if (lt == lq && rt == rq) {
      return node[root].sum;
    }
    PushDown(root, lt, rt);
    int mid = lt + ((rt - lt) >> 1);
    if (rq <= mid) {
      return GetSum(ls(root), lt, mid, lq, rq);
    } else if (lq > mid) {
      return GetSum(rs(root), mid + 1, rt, lq, rq);
    } else {
      return GetSum(ls(root), lt, mid, lq, mid) + GetSum(rs(root), mid + 1, rt, mid + 1, rq);
    }
  }

  double GetSqSum(int root, int lt, int rt, int lq, int rq) {
    if (lt == lq && rt == rq) {
      return node[root].sqsum;
    }
    PushDown(root, lt, rt);
    int mid = lt + ((rt - lt) >> 1);
    if (rq <= mid) {
      return GetSqSum(ls(root), lt, mid, lq, rq);
    } else if (lq > mid) {
      return GetSqSum(rs(root), mid + 1, rt, lq, rq);
    } else {
      return GetSqSum(ls(root), lt, mid, lq, mid) + GetSqSum(rs(root), mid + 1, rt, mid + 1, rq);
    }
  }

  double GetAvg(int root, int lt, int rt, int lq, int rq) {
    double sum = GetSum(root, lt, rt, lq, rq);
    return sum / 1.0 / (rq - lq + 1);
  }

  double GetSq(int root, int lt, int rt, int lq, int rq) {
    double sqsum = GetSqSum(root, lt, rt, lq, rq);
    double avg = GetAvg(root, lt, rt, lq, rq);
    return sqsum / 1.0 / (rq - lq + 1) - avg * avg;
  }
} T;

int n, m;
double a[MAXN];

int main() {
  freopen("variance.in", "r", stdin);
  freopen("variance.out", "w", stdout);
  scanf("%d %d", &n, &m);
  for (int i = 1; i <= n; ++i) {
    scanf("%lf", &a[i]);
  }
  T.Build(1, 1, n, a);
  while (m--) {
    int op, x, y;
    scanf("%d %d %d", &op, &x, &y);
    if (op == 1) {
      double k;
      scanf("%lf", &k);
      T.AddSeq(1, 1, n, x, y, k);
    } else if (op == 2) {
      printf("%.4lf\n", T.GetAvg(1, 1, n, x, y));
    } else {
      printf("%.4lf\n", T.GetSq(1, 1, n, x, y));
    }
  }
  return 0;
}