Submission #2432665


Source Code Expand

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
import java.io.BufferedReader;
import java.util.ArrayDeque;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskE solver = new TaskE();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskE {
        static final long MODULO = (long) 1e9 + 7;
        ArrayDeque<int[]> available = new ArrayDeque<>();
        int totalAllocated = 0;
        int n;
        int[] a;
        int[] w;

        int[] newMatrix() {
            ++totalAllocated;
            if (available.isEmpty()) {
                return new int[9];
            } else {
                int[] res = available.pop();
                Arrays.fill(res, 0);
                return res;
            }
        }

        void freeMatrix(int[] a) {
            --totalAllocated;
            available.push(a);
        }

        int[] mul(int[] a, int[] b) {
            int[] c = newMatrix();
            for (int i = 0; i < 3; ++i) {
                for (int j = 0; j < 3; ++j) {
                    long s = 0;
                    for (int k = 0; k < 3; ++k) s += a[(i) * 3 + k] * (long) b[(k) * 3 + j];
                    c[(i) * 3 + j] = (int) (s % MODULO);
                }
            }
            return c;
        }

        int[] add(int[] a, int[] b) {
            int[] c = newMatrix();
            for (int i = 0; i < 3; ++i) {
                for (int j = 0; j < 3; ++j) {
                    long s = a[(i) * 3 + j] + b[(i) * 3 + j];
                    c[(i) * 3 + j] = (int) (s % MODULO);
                }
            }
            return c;
        }

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            n = in.nextInt();
            a = new int[n];
            for (int i = 0; i < n; ++i) a[i] = in.nextInt();
            for (int i = 0, j = n - 1; i < j; ++i, --j) {
                int t = a[i];
                a[i] = a[j];
                a[j] = t;
            }
            int[] positions = new int[n];
            for (int i = 0; i < n; ++i) positions[i] = i;
            w = getW(a.clone());
            for (int x : w)
                if (x == 0) {
                    out.println(0);
                    return;
                }

            Description desc = doit(0, n - 1, positions);
            out.println(desc.inside[(2) * 3 + 0]);
            desc.freeAll();
            if (totalAllocated != 0) throw new RuntimeException("" + totalAllocated);
        }

        private int[] getW(int[] a) {
            Arrays.sort(a);
            int sofar = 0;
            int pos = a.length - 1;
            int[] w = new int[n];
            for (int i = n - 1; i >= 0; --i) {
                while (pos >= 0 && a[pos] == i + 1) {
                    ++sofar;
                    --pos;
                }
                w[i] = Math.max(0, sofar);
                --sofar;
            }
            return w;
        }

        private Description doit(int min, int max, int[] positions) {
            Description res = new Description();
            if (min == max) {
                res.p00then01 = new int[positions.length][];
                res.p00then10 = new int[positions.length][];
                res.p01then11 = new int[positions.length][];
                res.p10then11 = new int[positions.length][];
                int k = min;
                for (int x : positions) if (a[x] != k + 1) throw new RuntimeException();
                res.p00 = newMatrix();
                res.p00[(0) * 3 + 0] = w[k];
                res.p01 = newMatrix();
                res.p01[(0) * 3 + 0] = w[k] - 1;
                res.p01[(1) * 3 + 0] = 1;
                res.p01[(1) * 3 + 1] = w[k];
                res.p10 = newMatrix();
                res.p10[(0) * 3 + 0] = w[k] - 1;
                res.p11 = newMatrix();
                res.p11[(0) * 3 + 0] = Math.max(0, w[k] - 2);
                res.p11[(1) * 3 + 0] = 1;
                res.p11[(1) * 3 + 1] = w[k] - 1;
                res.p11[(2) * 3 + 1] = 1;
                res.p11[(2) * 3 + 2] = w[k];
                for (int i = 0; i < positions.length; ++i) {
                    res.p01then11[i] = copy(res.p11);
                    res.p10then11[i] = copy(res.p11);
                    res.p00then10[i] = copy(res.p10);
                    res.p00then01[i] = copy(res.p01);
                }
                int[] sum = newMatrix();
                res.inside = newMatrix();
                for (int x : positions) {
                    int[] tmp1 = res.inside;
                    res.inside = add(res.inside, sum);
                    freeMatrix(tmp1);
                    tmp1 = sum;
                    sum = add(sum, res.p11);
                    freeMatrix(tmp1);
                }
                freeMatrix(sum);
            } else {
                int mid = (min + max) / 2;
                int numBottom = 0;
                int numTop = 0;
                for (int x : positions)
                    if (a[x] <= mid + 1) {
                        ++numBottom;
                    } else {
                        ++numTop;
                    }
                int[] bottomPositions = new int[numBottom];
                int[] topPositions = new int[numTop];
                numBottom = 0;
                numTop = 0;
                for (int x : positions)
                    if (a[x] <= mid + 1) {
                        bottomPositions[numBottom++] = x;
                    } else {
                        topPositions[numTop++] = x;
                    }
                Description bottom;
                Description top;
                if (numBottom < numTop) {
                    bottom = doit(min, mid, bottomPositions);
                    top = doit(mid + 1, max, topPositions);
                } else {
                    top = doit(mid + 1, max, topPositions);
                    bottom = doit(min, mid, bottomPositions);
                }
                res.p00then01 = new int[positions.length][];
                res.p00then10 = new int[positions.length][];
                res.p01then11 = new int[positions.length][];
                res.p10then11 = new int[positions.length][];
                int[] tmp1 = mul(bottom.inside, top.p00);
                int[] tmp2 = mul(bottom.p11, top.inside);
                res.inside = add(tmp1, tmp2);
                freeMatrix(tmp1);
                freeMatrix(tmp2);
                res.p00 = mul(bottom.p00, top.p00);
                res.p11 = mul(bottom.p11, top.p11);
                res.p01 = mul(bottom.p01, top.p01);
                res.p10 = mul(bottom.p10, top.p10);
                int topPtr = 0;
                int bottomPtr = 0;
                int[] topSum = newMatrix();
                int[] bottomSum = newMatrix();
                int ptr = 0;
                for (int x : positions)
                    if (a[x] <= mid + 1) {
                        res.p00then01[ptr] = mul(bottom.p00then01[bottomPtr], top.p00);
                        res.p00then10[ptr] = mul(bottom.p00then10[bottomPtr], top.p00);
                        res.p10then11[ptr] = mul(bottom.p10then11[bottomPtr], top.p10);
                        res.p01then11[ptr] = mul(bottom.p01then11[bottomPtr], top.p01);
                        tmp1 = mul(bottom.p10then11[bottomPtr], topSum);
                        tmp2 = res.inside;
                        res.inside = add(res.inside, tmp1);
                        freeMatrix(tmp1);
                        freeMatrix(tmp2);
                        tmp2 = bottomSum;
                        bottomSum = add(bottomSum, bottom.p01then11[bottomPtr]);
                        freeMatrix(tmp2);
                        ++bottomPtr;
                        ++ptr;
                    } else {
                        res.p00then01[ptr] = mul(bottom.p01, top.p00then01[topPtr]);
                        res.p00then10[ptr] = mul(bottom.p10, top.p00then10[topPtr]);
                        res.p10then11[ptr] = mul(bottom.p11, top.p10then11[topPtr]);
                        res.p01then11[ptr] = mul(bottom.p11, top.p01then11[topPtr]);
                        tmp1 = mul(bottomSum, top.p00then01[topPtr]);
                        tmp2 = res.inside;
                        res.inside = add(res.inside, tmp1);
                        freeMatrix(tmp1);
                        freeMatrix(tmp2);
                        tmp2 = topSum;
                        topSum = add(topSum, top.p00then10[topPtr]);
                        freeMatrix(tmp2);
                        ++topPtr;
                        ++ptr;
                    }
                freeMatrix(bottomSum);
                freeMatrix(topSum);
                bottom.freeAll();
                top.freeAll();
            }
            return res;
        }

        private int[] copy(int[] a) {
            int[] b = newMatrix();
            System.arraycopy(a, 0, b, 0, 9);
            return b;
        }

        class Description {
            int[] inside;
            int[] p00;
            int[] p11;
            int[] p01;
            int[] p10;
            public int[][] p10then11;
            public int[][] p01then11;
            public int[][] p00then01;
            public int[][] p00then10;

            public void freeAll() {
                freeMatrix(inside);
                freeMatrix(p00);
                freeMatrix(p01);
                freeMatrix(p11);
                freeMatrix(p10);
                for (int[] x : p10then11) freeMatrix(x);
                for (int[] x : p01then11) freeMatrix(x);
                for (int[] x : p00then01) freeMatrix(x);
                for (int[] x : p00then10) freeMatrix(x);
            }

        }

    }

    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

    }
}

Submission Info

Submission Time
Task E - Inversions
User Petr
Language Java7 (OpenJDK 1.7.0)
Score 1700
Code Size 11268 Byte
Status AC
Exec Time 2473 ms
Memory 238180 KB

Judge Result

Set Name Sample All
Score / Max Score 0 / 0 1700 / 1700
Status
AC × 4
AC × 43
Set Name Test Cases
Sample sample_01.txt, sample_02.txt, sample_03.txt, sample_04.txt
All sample_01.txt, sample_02.txt, sample_03.txt, sample_04.txt, sample_01.txt, sample_02.txt, sample_03.txt, sample_04.txt, subtask_1_01.txt, subtask_1_02.txt, subtask_1_03.txt, subtask_1_04.txt, subtask_1_05.txt, subtask_1_06.txt, subtask_1_07.txt, subtask_1_08.txt, subtask_1_09.txt, subtask_1_10.txt, subtask_1_11.txt, subtask_1_12.txt, subtask_1_13.txt, subtask_1_14.txt, subtask_1_15.txt, subtask_1_16.txt, subtask_1_17.txt, subtask_1_18.txt, subtask_1_19.txt, subtask_1_20.txt, subtask_1_21.txt, subtask_1_22.txt, subtask_1_23.txt, subtask_1_24.txt, subtask_1_25.txt, subtask_1_26.txt, subtask_1_27.txt, subtask_1_28.txt, subtask_1_29.txt, subtask_1_30.txt, subtask_1_31.txt, subtask_1_32.txt, subtask_1_33.txt, subtask_1_34.txt, subtask_1_35.txt
Case Name Status Exec Time Memory
sample_01.txt AC 76 ms 16852 KB
sample_02.txt AC 77 ms 18772 KB
sample_03.txt AC 76 ms 20692 KB
sample_04.txt AC 96 ms 17620 KB
subtask_1_01.txt AC 76 ms 18644 KB
subtask_1_02.txt AC 75 ms 16852 KB
subtask_1_03.txt AC 330 ms 45372 KB
subtask_1_04.txt AC 179 ms 25740 KB
subtask_1_05.txt AC 1159 ms 70088 KB
subtask_1_06.txt AC 2018 ms 195308 KB
subtask_1_07.txt AC 1026 ms 75920 KB
subtask_1_08.txt AC 1060 ms 116828 KB
subtask_1_09.txt AC 1214 ms 114228 KB
subtask_1_10.txt AC 1169 ms 82132 KB
subtask_1_11.txt AC 1546 ms 129232 KB
subtask_1_12.txt AC 1532 ms 123720 KB
subtask_1_13.txt AC 1890 ms 198388 KB
subtask_1_14.txt AC 314 ms 45780 KB
subtask_1_15.txt AC 340 ms 43976 KB
subtask_1_16.txt AC 2473 ms 238180 KB
subtask_1_17.txt AC 2092 ms 187280 KB
subtask_1_18.txt AC 2243 ms 188776 KB
subtask_1_19.txt AC 2183 ms 184548 KB
subtask_1_20.txt AC 2215 ms 190008 KB
subtask_1_21.txt AC 2198 ms 189124 KB
subtask_1_22.txt AC 2311 ms 192928 KB
subtask_1_23.txt AC 2237 ms 187500 KB
subtask_1_24.txt AC 2256 ms 187632 KB
subtask_1_25.txt AC 393 ms 47080 KB
subtask_1_26.txt AC 352 ms 47608 KB
subtask_1_27.txt AC 2195 ms 187596 KB
subtask_1_28.txt AC 2416 ms 191152 KB
subtask_1_29.txt AC 2049 ms 185896 KB
subtask_1_30.txt AC 2160 ms 183444 KB
subtask_1_31.txt AC 2223 ms 191572 KB
subtask_1_32.txt AC 2234 ms 189936 KB
subtask_1_33.txt AC 2457 ms 192400 KB
subtask_1_34.txt AC 2308 ms 186920 KB
subtask_1_35.txt AC 2243 ms 186656 KB