#include <bits/stdc++.h>
using namespace std;
struct RMQ {
 public:
  RMQ(const vector<int>& a, int leftIndex = -1, int rightIndex = -1) {
    if (rightIndex == -1) {
      leftIndex = 0;
      rightIndex = a.size() - 1;
    }
    this->leftIndex = leftIndex;
    this->rightIndex = rightIndex;
    if (leftIndex == rightIndex)
      this->minVal = a[leftIndex];
    else {
      this->midIndex = (leftIndex + rightIndex) / 2;
      RMQ leftChild = RMQ(a, leftIndex, this->midIndex);
      RMQ rightChild = RMQ(a, this->midIndex + 1, rightIndex);
      this->minVal = max(leftChild.minVal, rightChild.minVal);
      this->children.push_back(leftChild);
      this->children.push_back(rightChild);
    }
  }
  int minQuery(int left, int right) {
    if (left == this->leftIndex and right == this->rightIndex)
      return this->minVal;
    if (right <= this->midIndex) return this->children[0].minQuery(left, right);
    if (left > this->midIndex) return this->children[1].minQuery(left, right);
    return max(this->children[0].minQuery(left, this->midIndex),
               this->children[1].minQuery(this->midIndex + 1, right));
  }

 private:
  int leftIndex, rightIndex, midIndex;
  int minVal;
  vector<RMQ> children;
};
struct Distribution {
 public:
  int minValue;
  vector<double> cdf;
  Distribution(int minValue = 0, vector<double> cdf = vector<double>()) {
    this->minValue = minValue;
    this->cdf = cdf;
  }
  Distribution maxDistribution(vector<Distribution>& otherDistributions) {
    if (otherDistributions.empty()) return *this;
    int newMinVal = this->minValue;
    int newMaxVal = this->minValue + this->cdf.size() - 1;
    for (int i = 0; i < otherDistributions.size(); i++) {
      newMinVal = max(newMinVal, otherDistributions[i].minValue);
      newMaxVal = max(newMaxVal, (int)(otherDistributions[i].minValue +
                                       otherDistributions[i].cdf.size() - 1));
    }
    vector<double> newCdf(newMaxVal - newMinVal + 1);
    for (int i = 0; i < newCdf.size(); i++) newCdf[i] = (double)(1e12 + 0.01);
    for (int i = 0; i < newCdf.size(); i++) {
      for (int j = 0; j < otherDistributions.size(); j++) {
        int newIndex = i + (newMinVal - otherDistributions[j].minValue);
        if (newIndex < otherDistributions[j].cdf.size()) {
          newCdf[i] *= otherDistributions[j].cdf[newIndex];
          newCdf[i] /= (double)(1e12 + 0.01);
        }
      }
    }
    return Distribution(newMinVal, newCdf);
  }
};
struct Interval {
 public:
  int left, right, mx;
  double p;
  vector<Interval> children;
  Distribution distribution;
  Interval(int left = -1, int right = -1, double p = -1, int mx = -1) {
    this->left = left;
    this->right = right;
    this->p = p;
    this->mx = mx;
    vector<double> cdf;
    cdf.push_back((double)(1e12 + 0.01));
    this->distribution = Distribution(mx, cdf);
  }
  void insertInterval(Interval i) {
    for (int j = 0; j < this->children.size(); j++) {
      if (this->children[j].left <= i.left and
          i.right <= this->children[j].right) {
        this->children[j].insertInterval(i);
        return;
      }
    }
    this->children.push_back(i);
  }
  Distribution getDistribution() {
    vector<Distribution> otherDistributions;
    for (int i = 0; i < this->children.size(); i++) {
      otherDistributions.push_back(this->children[i].getDistribution());
    }
    Distribution inside =
        this->distribution.maxDistribution(otherDistributions);
    inside.cdf.push_back((double)(1e12 + 0.01));
    for (int i = inside.cdf.size() - 2; i > 0; i--) {
      inside.cdf[i] =
          inside.cdf[i - 1] + (((double)(1e12 + 0.01) - this->p) *
                               (inside.cdf[i] - inside.cdf[i - 1])) /
                                  (double)(1e12 + 0.01);
    }
    inside.cdf[0] *= ((double)(1e12 + 0.01) - this->p);
    inside.cdf[0] /= (double)(1e12 + 0.01);
    return inside;
  }
};
int n, q, l, r;
double p;
vector<int> a;
int main(void) {
  cin >> n >> q;
  a.resize(n);
  for (int i = 0; i < n; i++) {
    cin >> a[i];
  }
  RMQ aRMQ = RMQ(a);
  Interval everything =
      Interval(0, a.size() - 1, 0, aRMQ.minQuery(0, a.size() - 1));
  Interval z;
  vector<pair<pair<int, int>, double> > intvals;
  for (int i = 0; i < q; i++) {
    cin >> l >> r >> p;
    l--;
    r--;
    p *= (double)(1e12 + 0.01);
    intvals.push_back(pair<pair<int, int>, double>(pair<int, int>(l, -r), p));
  }
  sort(intvals.begin(), intvals.end());
  for (int i = 0; i < intvals.size(); i++) {
    l = intvals[i].first.first;
    r = -intvals[i].first.second;
    p = intvals[i].second;
    Interval newInterval = Interval(l, r, p, aRMQ.minQuery(l, r));
    everything.insertInterval(newInterval);
  }
  Distribution overall = everything.getDistribution();
  double ev = (double)(1e12 + 0.01) * (double)overall.minValue;
  for (int i = 1; i < overall.cdf.size(); i++) {
    ev += (i * (overall.cdf[i] - overall.cdf[i - 1]));
  }
  ev /= (double)(1e12 + 0.01);
  cout << setprecision(20) << ev;
}
