Problem:
イルミネーション (Illumination)

問題文

JOI 氏は，自宅の敷地に N 本の木を所有している．これらの木は一列に並んでおり，順に 1 から N までの整数で番号が付けられている．

この冬，JOI 氏はいくつかの木を選んで，イルミネーションを飾り付けることにした．イルミネーションには美しさと呼ばれる値が定まっている．木 i にイルミネーションを飾り付ける場合の美しさは A_i である．

JOI 氏は，あまりに近い 2 つの木の両方にイルミネーションを飾り付けてしまうと，眩しすぎる場合があることに気がついた．具体的には，j = 1, 2, ..., M に対して，木 L_j, L_j + 1, ..., R_j のうち 2 つ以上にイルミネーションを飾り付けるべきではないということが判明した．

この条件に従ってイルミネーションを飾り付けるときの，美しさの合計の最大値を求めよ．

制約

1 ≦ N ≦ 200000 (= 2×10^5)

1 ≦ M ≦ 200000 (= 2×10^5)

1 ≦ A_i ≦ 1000000000 (= 10^9) (1 ≦ i ≦ N)

1 ≦ L_j ≦ R_j ≦ N (1 ≦ j ≦ M)

入力・出力

入力

入力は以下の形式で標準入力から与えられる．

N M

A_1 A_2 ... A_N

L_1 R_1

L_2 R_2

⋮

L_M R_M

出力

イルミネーションの美しさの合計の最大値を 1 行で出力せよ．

入出力例

入力例 1

4 1
1 2 3 8
2 4

出力例 1

9

この入力例では，木 1, 4 にイルミネーションを飾り付けると，美しさの合計が 9 となり最大となる．L_1 = 2, R_1 = 4 なので，木 2, 3, 4 のうち 2 つ以上にイルミネーションを飾り付けることはできない．例えば木 1, 2, 4 にイルミネーションを飾り付けることはできないことに注意せよ．

入力例 2

5 2
2 3 9 5 6
1 3
2 4

出力例 2

15

入力例 3

20 10
870851814 594414687 615919461 65033245 460143082 617460823 881870957 126041265 623075703 34130727 27054628 853567651 483228744 491145755 220689940 148007930 229257101 790404982 612186806 281076231
15 19
20 20
12 13
1 4
19 19
9 13
3 6
9 12
16 16
18 19

出力例 3

4912419478

情報オリンピック日本委員会作 『第 18 回日本情報オリンピック JOI 2018/2019 予選競技課題』

Solution in JAVA (judge verdict: Time Limit Exceeded)

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

class Main {

	static long[] beauty;  //美しさ
	static int[] L;
	static int[] R;

	public static void main(String[] args) {
		try (Scanner sc = new Scanner(System.in)){
			int treeNum = sc.nextInt();
			beauty = new long[treeNum];
			boolean[] illumination = new boolean[treeNum];  //イルミネーション trueついてる falseついてない
			int mNum = sc.nextInt();
			L = new int[mNum];
			R = new int[mNum];
			for (int i=0; i<treeNum; i++) {
				beauty[i] = sc.nextLong();  //美しさを読み込み
				illumination[i]  = true;
			}
			for (int i=0; i<mNum; i++) {  //LとRをストック
				L[i] = sc.nextInt()-1;
				R[i] = sc.nextInt()-1;
			}
			List<Long> beautys = new ArrayList<Long>();
			beautys = allPattern(beautys,illumination,0);
			long max_beauty = 0l;
			for (long l : beautys) {
				max_beauty = Math.max(max_beauty, l);
			}
			System.out.println(max_beauty);
		}
	}

	public static List<Long> allPattern(List<Long> beautys,boolean[] illu, int pointer){
		if (pointer >= L.length) {  //命令の数
			Long b = 0l;
			for (int i=0; i<beauty.length; i++) {
				//System.out.println(i + "-------" + illu[i]);
				if (illu[i]) {  //ついているなら
					b += beauty[i];  //美しさを加算
				}
			}
			//System.out.println(b);
			beautys.add(b);
		} else {
			for (int i=L[pointer]; i<=R[pointer]; i++) {
				boolean[] copy = new boolean[illu.length];
				for (int j=0; j<illu.length; j++) copy[j] = illu[j];  //コピーする
				for (int j=L[pointer]; j<=R[pointer]; j++) copy[j] = false;  //まず範囲内をイルミネーションを全部消す
				if (illu[i]) {  //すでに消したら処理しない
					copy[i] = true;  //一個ずつつけて再帰する
				}
				allPattern(beautys,copy,pointer+1);
			}

		}
		return beautys;
	}
}