import java.util.Arrays;
import java.util.stream.IntStream;
import java.util.concurrent.ForkJoinTask;

class Example {
    static final int SEQUENTIAL_CUTOFF = 1;

    static void prefixSumUp(int[] in, int out[], int lo, int hi) {
        if (hi-lo <= SEQUENTIAL_CUTOFF) {
            out[hi-1] = IntStream.range(lo, hi).map(i->in[i]).sum();
        } else {
            ForkJoinTask<?> left = ForkJoinTask.adapt(() ->
                prefixSumUp(in, out, lo, (lo+hi)/2)).fork();
            prefixSumUp(in, out, (lo+hi)/2, hi);
            left.join();
            out[hi-1] += out[(lo+hi)/2-1];
        }
    }

    static void prefixSumDown(int[] in, int[] out, int lo, int hi, int fromLeft) {
        if (hi-lo <= SEQUENTIAL_CUTOFF) {
            int ans = fromLeft;
            for (int i=lo; i<hi; ++i) {
                ans += in[i];
                out[i] = ans;
            }
        } else {
            int fromLeft2 = fromLeft + out[(lo+hi)/2-1];
            ForkJoinTask<?> left = ForkJoinTask.adapt(() ->
                prefixSumDown(in, out, lo, (lo+hi)/2, fromLeft)).fork();
            prefixSumDown(in, out, (lo+hi)/2, hi, fromLeft2);
            left.join();
        }
    }

    public static void main(String[] args) throws Exception {
        int[] in = {6, 4, 16, 10, 16, 14, 2, 8};
        int[] out = new int[in.length];

        System.out.println(Arrays.toString(in));
        prefixSumUp(in, out, 0, in.length);
        System.out.println(Arrays.toString(out));
        prefixSumDown(in, out, 0, in.length, 0);
        System.out.println(Arrays.toString(out));
    }
}