Problem: Malek is a rich man. He also is very generous. That's why he decided to split his money between poor people. A charity institute knows n poor people numbered from 1 to n. The institute gave Malek q recommendations. A recommendation is a segment of people like [l, r] which means the institute recommended that Malek gives one dollar to every person whose number is in this segment.

However this charity has very odd rules about the recommendations. Because of those rules the recommendations are given in such a way that for every two recommendation [a, b] and [c, d] one of the following conditions holds: 

  * The two segments are completely disjoint. More formally either a ≤ b < c ≤ d or c ≤ d < a ≤ b
  * One of the two segments are inside another. More formally either a ≤ c ≤ d ≤ b or c ≤ a ≤ b ≤ d. 



The goodness of a charity is the value of maximum money a person has after Malek finishes giving his money. The institute knows for each recommendation what is the probability that Malek will accept it. They want to know the expected value of goodness of this charity. So they asked you for help.

You have been given the list of recommendations and for each recommendation the probability of it being accepted by Malek. You have also been given how much money each person initially has. You must find the expected value of goodness.

Input

In the first line two space-separated integers n, q (1 ≤ n ≤ 105, 1 ≤ q ≤ 5000) are given.

In the second line n space-separated integers a1, a2, ..., an (0 ≤ ai ≤ 109) are given meaning that person number i initially has ai dollars. 

Each of the next q lines contains three space-separated numbers li, ri, pi (1 ≤ li ≤ ri ≤ n, 0 ≤ p ≤ 1) where li and ri are two integers describing the segment of recommendation and pi is a real number given with exactly three digits after decimal point which is equal to probability of Malek accepting this recommendation.

Note that a segment may appear several times in recommendations.

Output

Output the sought value. Your answer will be considered correct if its absolute or relative error is less than 10 - 6.

Examples

Input

5 2
1 7 2 4 3
1 3 0.500
2 2 0.500


Output

8.000000000


Input

5 2
281 280 279 278 282
1 4 1.000
1 4 0.000


Output

282.000000000


Input

3 5
1 2 3
1 3 0.500
2 2 0.250
1 2 0.800
1 1 0.120
2 2 0.900


Output

4.465000000

Solution (in JAVA):

Solution:
import java.io.BufferedWriter;
import java.util.InputMismatchException;
import java.util.NoSuchElementException;
import java.math.BigInteger;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Writer;
import java.io.IOException;
import java.util.Arrays;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.util.Comparator;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 * @author Nguyen Trung Hieu - vuondenthanhcong11@gmail.com
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        OutputWriter out = new OutputWriter(outputStream);
        TaskC solver = new TaskC();
        solver.solve(1, in, out);
        out.close();
    }
}

class TaskC {
    public void solve(int testNumber, InputReader in, OutputWriter out) {
        int count = in.readInt();
        int segmentCount = in.readInt();
        int[] A = IOUtils.readIntArray(in, count);
        Rec[] segments = new Rec[segmentCount + 1];

        for (int i = 0; i < segmentCount; i++) {
            segments[i] = new Rec(in.readInt() - 1, in.readInt() - 1, in.readDouble());
        }

        segments[segmentCount] = new Rec(0, count - 1, 0);

        Arrays.sort(segments, new Comparator<Rec>() {
            public int compare(Rec o1, Rec o2) {
                if (o1.left != o2.left)
                    return o1.left - o2.left;
                return o2.right - o1.right;
            }
        });

        int[] party = new int[segmentCount + 1];
        for (int i = 0; i < segmentCount + 1; i++) {
            party[i] = -1;
            for (int j = i - 1; j >= 0; j--) {
                if (segments[j].left <= segments[i].left && segments[i].right <= segments[j].right) {
                    party[i] = j;
                    break;
                }
            }
        }

        IntervalTree tree = new LongIntervalTree(count) {
            protected long joinValue(long left, long right) {
                return Math.max(left, right);
            }

            protected long joinDelta(long was, long delta) {
                return Math.max(was, delta);
            }

            protected long accumulate(long value, long delta, int length) {
                return Math.max(value, delta);
            }

            protected long neutralValue() {
                return 0;
            }

            protected long neutralDelta() {
                return 0;
            }
        };

        for (int i = 0; i < count; i++) {
            tree.update(i, i, A[i]);
        }

        double[][] dp = new double[segmentCount + 1][];
        int[][] g = parentToG(party);
        int[][] parties = parents(g, 0);
        int[] ord = parties[1];
        int[] base = new int[segmentCount + 1];
        for (int i = segmentCount; i >= 0; i--) {
            int cur = ord[i];
            base[cur] = (int)tree.query(segments[cur].left, segments[cur].right);
            int dplen = 2;
            for (int e : g[cur]) {
                if (party[cur] != e) {
                    dplen = Math.max(dplen, dp[e].length - (base[cur] - base[e]) + 1);
                }
            }
            double[] pr = new double[dplen];
            pr[0] = 1;
            for (int e : g[cur]) {
                if (party[cur] != e) {
                    if (dp[e].length - (base[cur] - base[e]) > 0) {
                        double[] prsum = Arrays.copyOf(pr, dplen);
                        for (int j = 1; j < dplen; j++) {
                            prsum[j] += prsum[j - 1];
                        }
                        double fall = 0;
                        for (int j = dp[e].length - 1, k = base[e] + j; k >= base[cur]; k--, j--) {
                            pr[k - base[cur]] *= 1 - fall;
                            if (k - base[cur] - 1 >= 0)
                                pr[k - base[cur]] += prsum[k - base[cur] - 1] * dp[e][j];
                            fall += dp[e][j];
                        }
                    }
                }
            }

            for (int j = dplen - 2; j >= 0; j--) {
                pr[j + 1] += pr[j] * segments[cur].probability;
                pr[j] *= 1 - segments[cur].probability;
            }

            dp[cur] = pr;
        }

        double e = 0;
        for (int i = 0; i < dp[0].length; i++) {
            e += dp[0][i] * (base[0] + i);
        }

        out.printLine(e);
    }

    private int[][] parents(int[][] g, int root) {
        int count = g.length;
        int[] party = new int[count];
        Arrays.fill(party, -1);

        int[] q = new int[count];
        q[0] = root;
        for (int p = 0, r = 1; p < r; p++) {
            int cur = q[p];
            for (int next : g[cur]) {
                if (party[cur] != next) {
                    q[r++] = next;
                    party[next] = cur;
                }
            }
        }

        return new int[][]{party, q};
    }

    private int[][] parentToG(int[] party) {
        int count = party.length;
        int[] ct = new int[count];
        for (int i = 0; i < count; i++) {
            if (party[i] >= 0) {
                ct[i]++;
                ct[party[i]]++;
            }
        }

        int[][] g = new int[count][];
        for (int i = 0; i < count; i++) {
            g[i] = new int[ct[i]];
        }
        for (int i = 0; i < count; i++) {
            if (party[i] >= 0) {
                g[party[i]][--ct[party[i]]] = i;
                g[i][--ct[i]] = party[i];
            }
        }

        return g;
    }

    static class Rec{
        public int left, right;
        public double probability;
        public Rec(int left, int right, double probability) {
            this.left = left;
            this.right = right;
            this.probability = probability;
        }
    }
}

class InputReader {
    private InputStream stream;
    private byte[] buf = new byte[1024];
    private int curChar;
    private int numChars;
    private SpaceCharFilter filter;

    public InputReader(InputStream stream) {
        this.stream = stream;
    }

    public int read() {
        if (numChars == -1)
            throw new InputMismatchException();
        if (curChar >= numChars) {
            curChar = 0;
            try {
                numChars = stream.read(buf);
            } catch (IOException e) {
                throw new InputMismatchException();
            }
            if (numChars <= 0)
                return -1;
        }
        return buf[curChar++];
    }

    public int readInt() {
        int c = read();
        while (isSpaceChar(c))
            c = read();
        int sgn = 1;
        if (c == '-') {
            sgn = -1;
            c = read();
        }
        int res = 0;
        do {
            if (c < '0' || c > '9')
                throw new InputMismatchException();
            res *= 10;
            res += c - '0';
            c = read();
        } while (!isSpaceChar(c));
        return res * sgn;
    }

    public boolean isSpaceChar(int c) {
        if (filter != null)
            return filter.isSpaceChar(c);
        return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
    }

    public interface SpaceCharFilter {
        public boolean isSpaceChar(int ch);
    }

    public double readDouble() {
        int c = read();
        while (isSpaceChar(c))
            c = read();
        int sgn = 1;
        if (c == '-') {
            sgn = -1;
            c = read();
        }
        double res = 0;
        while (!isSpaceChar(c) && c != '.') {
            if (c == 'e' || c == 'E')
                return res * Math.pow(10, readInt());
            if (c < '0' || c > '9')
                throw new InputMismatchException();
            res *= 10;
            res += c - '0';
            c = read();
        }
        if (c == '.') {
            c = read();
            double m = 1;
            while (!isSpaceChar(c)) {
                if (c == 'e' || c == 'E')
                    return res * Math.pow(10, readInt());
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                m /= 10;
                res += (c - '0') * m;
                c = read();
            }
        }
        return res * sgn;
    }

}

class OutputWriter {
    private final PrintWriter writer;

    public OutputWriter(OutputStream outputStream) {
        writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
    }

    public void print(Object...objects) {
        for (int i = 0; i < objects.length; i++) {
            if (i != 0)
                writer.print(' ');
            writer.print(objects[i]);
        }
    }

    public void printLine(Object...objects) {
        print(objects);
        writer.println();
    }

    public void close() {
        writer.close();
    }

}

class IOUtils {

    public static int[] readIntArray(InputReader in, int size) {
        int[] array = new int[size];
        for (int i = 0; i < size; i++)
            array[i] = in.readInt();
        return array;
    }

}

abstract class IntervalTree {
    protected int size;

    public IntervalTree(int size, boolean shouldInit) {
        this.size = size;
        int nodeCount = Math.max(1, Integer.highestOneBit(size) << 2);
        initData(size, nodeCount);
        if (shouldInit)
            init();
    }

    protected abstract void initData(int size, int nodeCount);
    protected abstract void initAfter(int root, int left, int right, int middle);
    protected abstract void initBefore(int root, int left, int right, int middle);
    protected abstract void initLeaf(int root, int index);
    protected abstract void updatePostProcess(int root, int left, int right, int from, int to, long delta, int middle);
    protected abstract void updatePreProcess(int root, int left, int right, int from, int to, long delta, int middle);
    protected abstract void updateFull(int root, int left, int right, int from, int to, long delta);
    protected abstract long queryPostProcess(int root, int left, int right, int from, int to, int middle, long leftResult, long rightResult);
    protected abstract void queryPreProcess(int root, int left, int right, int from, int to, int middle);
    protected abstract long queryFull(int root, int left, int right, int from, int to);
    protected abstract long emptySegmentResult();

    public void init() {
        if (size == 0)
            return;
        init(0, 0, size - 1);
    }

    private void init(int root, int left, int right) {
        if (left == right) {
            initLeaf(root, left);
        } else {
            int middle = (left + right) >> 1;
            initBefore(root, left, right, middle);
            init(2 * root + 1, left, middle);
            init(2 * root + 2, middle + 1, right);
            initAfter(root, left, right, middle);
        }
    }

    public void update(int from, int to, long delta) {
        update(0, 0, size - 1, from, to, delta);
    }

    protected void update(int root, int left, int right, int from, int to, long delta) {
        if (left > to || right < from)
            return;
        if (left >= from && right <= to) {
            updateFull(root, left, right, from, to, delta);
            return;
        }
        int middle = (left + right) >> 1;
        updatePreProcess(root, left, right, from, to, delta, middle);
        update(2 * root + 1, left, middle, from, to, delta);
        update(2 * root + 2, middle + 1, right, from, to, delta);
        updatePostProcess(root, left, right, from, to, delta, middle);
    }

    public long query(int from, int to) {
        return query(0, 0, size - 1, from, to);
    }

    protected long query(int root, int left, int right, int from, int to) {
        if (left > to || right < from)
            return emptySegmentResult();
        if (left >= from && right <= to)
            return queryFull(root, left, right, from, to);
        int middle = (left + right) >> 1;
        queryPreProcess(root, left, right, from, to, middle);
        long leftResult = query(2 * root + 1, left, middle, from, to);
        long rightResult = query(2 * root + 2, middle + 1, right, from, to);
        return queryPostProcess(root, left, right, from, to, middle, leftResult, rightResult);
    }
}

abstract class LongIntervalTree extends IntervalTree {
    protected long[] value;
    protected long[] delta;

    protected LongIntervalTree(int size) {
        this(size, true);
    }

    public LongIntervalTree(int size, boolean shouldInit) {
        super(size, shouldInit);
    }

    protected void initData(int size, int nodeCount) {
        value = new long[nodeCount];
        delta = new long[nodeCount];
    }

    protected abstract long joinValue(long left, long right);
    protected abstract long joinDelta(long was, long delta);
    protected abstract long accumulate(long value, long delta, int length);
    protected abstract long neutralValue();
    protected abstract long neutralDelta();

    protected long initValue(int index) {
        return neutralValue();
    }

    protected void initAfter(int root, int left, int right, int middle) {
        value[root] = joinValue(value[2 * root + 1], value[2 * root + 2]);
        delta[root] = neutralDelta();
    }

    protected void initBefore(int root, int left, int right, int middle) {
    }

    protected void initLeaf(int root, int index) {
        value[root] = initValue(index);
        delta[root] = neutralDelta();
    }

    protected void updatePostProcess(int root, int left, int right, int from, int to, long delta, int middle) {
        value[root] = joinValue(value[2 * root + 1], value[2 * root + 2]);
    }

    protected void updatePreProcess(int root, int left, int right, int from, int to, long delta, int middle) {
        pushDown(root, left, middle, right);
    }

    protected void pushDown(int root, int left, int middle, int right) {
        value[2 * root + 1] = accumulate(value[2 * root + 1], delta[root], middle - left + 1);
        value[2 * root + 2] = accumulate(value[2 * root + 2], delta[root], right - middle);
        delta[2 * root + 1] = joinDelta(delta[2 * root + 1], delta[root]);
        delta[2 * root + 2] = joinDelta(delta[2 * root + 2], delta[root]);
        delta[root] = neutralDelta();
    }

    protected void updateFull(int root, int left, int right, int from, int to, long delta) {
        value[root] = accumulate(value[root], delta, right - left + 1);
        this.delta[root] = joinDelta(this.delta[root], delta);
    }

    protected long queryPostProcess(int root, int left, int right, int from, int to, int middle, long leftResult, long rightResult) {
        return joinValue(leftResult, rightResult);
    }

    protected void queryPreProcess(int root, int left, int right, int from, int to, int middle) {
        pushDown(root, left, middle, right);
    }

    protected long queryFull(int root, int left, int right, int from, int to) {
        return value[root];
    }

    protected long emptySegmentResult() {
        return neutralValue();
    }
}