vremenska_prognoza

Radnici u jednoj meteorološkoj stanici su napravili vremensku prognozu koja predviđa temperaturu za narednih \(n\) dana. Od značaja su im naredni upiti:

Implementirati program koji efikasno realizuje pomenute upite. Podrazumevati da indeksi dana kreću od 1.

Opis ulaza

Sa standardnog ulaza se unosi broj dana \(n\) (\(1 \le n \le 10000\)), a zatim i predviđene temperature (realni brojevi) za narednih \(n\) dana. Nakon toga se unosi broj upita \(m\) (\(1 \le m \le 1000\)), a zatim i \(m\) upita u već opisanom formatu.

Opis izlaza

Za svaki od upita druge vrste ispisati prosečnu temperaturu u zasebnom redu.

Primer

Ulaz

5 22.4 25.1 27.2 31.1 28.5 3 p 2 4 u 3 28.1 p 2 4

Izlaz

27.8 28.1

Rešenje

Opis glavnog rešenja

U ovom bloku se opisuje glavno rešenje zadatka.

#include <iostream>
#include <vector>
#include <algorithm>
#include <utility> 
#include <limits>
#include <cmath>

using namespace std;

void build(vector<double> &tree, const vector<double> &arr,
         const int i, const int start, const int end) 
{
   if (start == end) {
      tree[i] = arr[start];
      return;
   }

   int mid = (start + end) / 2;

   build(tree, arr, 2 * i + 1, start,   mid);
   build(tree, arr, 2 * i + 2, mid + 1, end);

   tree[i] = tree[2*i + 1] + tree[2*i + 2];
}

void build(vector<double> &tree, const int n, const vector<double> &arr)
{
   build(tree, arr, 0, 0, n - 1);
}

double query(const vector<double> &tree, 
                  const int i, const int start, const int end, 
                  const int l, const int r) 
{
   if (r < start || l > end) {
      return 0;
   }

   if (l <= start && r >= end) {
      return tree[i];
   }

   int mid = (start + end) / 2;

   double sum_left  = query(tree, 2 * i + 1, start,   mid, l, r);
   double sum_right = query(tree, 2 * i + 2, mid + 1, end, l, r);

   return sum_left + sum_right;
}

double query(const vector<double> &tree, const int n, 
                  const int l, const int r)
{
   return query(tree, 0, 0, n - 1, l, r);
}

void update(vector<double> &tree, 
         const int i, const int start, const int end, 
         const int ind, const double val) 
{
   if (start == end) {
      tree[i] = val;
      return;
   } 

   int mid = (start + end) / 2;
   
   if (ind <= mid) {
      update(tree, 2 * i + 1, start,   mid, ind, val);
   } else {
      update(tree, 2 * i + 2, mid + 1, end, ind, val);
   }

   tree[i] = tree[2*i + 1] + tree[2*i + 2];
}

void update(vector<double> &tree, const int n, 
         const int ind, const double val)
{
   update(tree, 0, 0, n - 1, ind, val);
}

int main(void) 
{
   int n;
   cin >> n;

   vector<double> arr(n);
   for (int i = 0; i < n; i++) {
      cin >> arr[i];
   }

   const int height = ceil(log2(n));
   const int size = 2 * pow(2, height) - 1;

   vector<double> tree(size); 

   build(tree, n, arr);

   int q;
   cin >> q;

   while (q--) {
      char op; cin >> op;
      if (op == 'u') {
         int ind;
         double val; 
         cin >> ind >> val;
         update(tree, n, ind-1, val);
      } else if (op == 'p') {
         int l, r; cin >> l >> r;
         double sum = query(tree, n, l-1, r-1);
         cout << sum / (r - l + 1) << endl;
      } 
   }

   return 0;
}