<p>Given an integer array <code>nums</code> and an integer <code>k</code>, find three non-overlapping subarrays of length <code>k</code> with maximum sum and return them.</p>

<p>Return the result as a list of indices representing the starting position of each interval (<strong>0-indexed</strong>). If there are multiple answers, return the lexicographically smallest one.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>

<pre>
<strong>Input:</strong> nums = [1,2,1,2,6,7,5,1], k = 2
<strong>Output:</strong> [0,3,5]
<strong>Explanation:</strong> Subarrays [1, 2], [2, 6], [7, 5] correspond to the starting indices [0, 3, 5].
We could have also taken [2, 1], but an answer of [1, 3, 5] would be lexicographically larger.
</pre>

<p><strong class="example">Example 2:</strong></p>

<pre>
<strong>Input:</strong> nums = [1,2,1,2,1,2,1,2,1], k = 2
<strong>Output:</strong> [0,2,4]
</pre>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>1 &lt;= nums.length &lt;= 2 * 10<sup>4</sup></code></li>
	<li><code>1 &lt;= nums[i] &lt;&nbsp;2<sup>16</sup></code></li>
	<li><code>1 &lt;= k &lt;= floor(nums.length / 3)</code></li>
</ul>

class Solution {
    using LL = long long;
public:
    vector<int> maxSumOfThreeSubarrays(vector<int>& nums, int k) {
        int n = nums.size();
        vector<LL> presum(n+1);
        
        int memo[n+1][4];  // 初始化 memo
        nums.insert(nums.begin(), 0);  // 插入 0 保持 1-indexed
        for(int i = 1; i <= n; i++){
            presum[i] = presum[i-1] + nums[i];
        }
        vector<vector<LL>> dp(n+1, vector<LL>(4));
        LL maxVal = 0;
        int idx = 0;

        for(int i = k; i <= n-k; i++){
            if(maxVal < presum[i] - presum[i-k]){
                maxVal = presum[i] - presum[i-k];
                idx = i-k;
            }
            dp[i][1] = maxVal;
            
            memo[i-1][1] = idx; // 走到某點要構成最大值 的那個區間的頭?
        }

        maxVal = 0;
        for(int i = 2*k; i <= n-k; i++){
            if(maxVal < presum[i] - presum[i-k] + dp[i-k][1]){
                maxVal = presum[i] - presum[i-k] + dp[i-k][1];
                idx = i - k;
            }
            dp[i][2] = maxVal;
            
            memo[i-1][2] = idx;
        }

        // -1 x x x | x x x | x x x | x x x x x x x x x  k = 3
        maxVal = 0;
        for(int i = k*3; i <= n; i++){
            if(maxVal < presum[i] - presum[i-k] + dp[i-k][2]){
                maxVal = presum[i] - presum[i-k] + dp[i-k][2];
                idx = i - k;
            }
            dp[i][3] = maxVal;
            memo[i-1][3] = idx;
        }

        // now we know the start of third inteval is idx
        vector<int> res(3);
        int count = 2;
        
        while(count >= 0){
            res[count] = idx;
            count -= 1;
            if(idx-1 >= 0) idx = memo[idx-1][count+1];
        }

        return res;
    }
};

/*
dp[i][j] -> 走到 i 位置 時 已經選了0-2個 可以產生的最大sum 
n = 10^4 大概可以接受 nlgn 
*/
35643