// 一组非负整数的数据,0元素会把数据分段,然后最多有k次机会,
// 每次可以把一段的数据每一个值都减一。 
// 问,这k次机会使用完之后,这组数据的最小和
struct Solution41 {
    vector<vector<int>> res;
    void fenduan(vector<int>& arr, int s, int e) {
        for(int i = s; i <= e; ++i) {
            vector<int> seg(2, 0);
            if(arr[i] == 0) continue;           // 遇到0跳过
            seg[0] = i;                         // 连续非0段的第一个下标
            int j = i;
            while(j <= e && arr[j] != 0) j++;   // 寻找连续非0段的最后一个下标
            if(j == e) {                        // 直到最后一个也不为0
                seg[1] = j;
            } 
            else {
                seg[1] = j - 1;
            }
            res.push_back(seg);
            i = j;
        }
    }
    int arrSum(vector<int>& arr) {
        int sum = 0;
        for(auto it : arr) sum+=it;
        return sum;
    }
    int fun(vector<int>& arr, int k) {
        int sum  = arrSum(arr);
        int n = arr.size();
        fenduan(arr, 0, n-1);

        int cnt = 1;
        while(cnt <= k) {
            int n = res.size();
            int maxlen = 0, idx = 0;
            for(int i = 0; i < n; ++i) {
                if(maxlen <= res[i][1] - res[i][0] + 1) {
                    maxlen  = res[i][1] - res[i][0] + 1;
                    idx = i;
                }
            }
            
            int minv = INT_MAX;
            int l = res[idx][0], r = res[idx][1];
            for(int i = l; i <= r; ++i) {
                minv = min(minv, arr[i]);
            }
            for(int i = l; i <= r; ++i) {
                arr[i] -= minv;
            }
            res.erase(idx);
            fenduan(arr, l, r);

            if(cnt + minv <= k){
                sum -= maxlen*minv;
                cnt = cnt + minv + 1;
            }
            else {
                minv = k - cnt;
                sum -= maxlen*minv;
                break;
            }
        }

    }
};