Problem:
Problem D: Smell Searcher
Problem
廃津大学では強烈な香りを放つ
N
個の廃材が一列に並んでいます。
廃材には1から
N
の番号が順番にふられていて、
i
番目の廃材は強さ
a
i
の香りを放っています。
リヒト君は仕事で、すべての廃材の放つ香りの総和を求めるよう依頼されました。
香りの総和が
M
以上になると「大変きつい仕事」とみなされ特別支給金がもらえます。
この仕事を行うために、リヒト君は精度
R
の香り検出器を使います。
  精度
R
の香り検出器を使うと
i
番目の廃材の香りを測ろうとすると同時に
i
−
R
,
i
−
R
+1,...,
i
−1,
i
,
i
+1,...,
i
+
R
−1,
i
+
R
番目の廃材の香りも検出されます。言い換えると、閉区間[ max(
i
−
R
,1), min(
i
+
R
,
N
) ] の廃材の香りを検出します。ここで、max(
a
,
b
)は
a
と
b
の最大値、min(
a
,
b
)は
a
と
b
の最小値を表します。

  ただし、測った廃材の1つ隣の廃材の香りの強さは本来の香りの強さより
C
減らされ、2つ隣の廃材の強さ香りは本来の香りの強さより2*
C
減らされて検出されます。つまり、
j
(0≤
j
≤
R
)個隣にある廃材の香りの強さは
a
i
−
j
*
C
として検出されます。結果的に、
i
番目の廃材に精度
R
の検出器を使うことで検出された香りの強さの最大値が
i
番目の廃材の香りの強さとして認識されます。
精度の高い検出器を使うとその分費用がかかるため、リヒト君は検出器が認識した1から
N
番目の廃材の香りの総和が
M
以上になる最低の精度
R
の値を知りたいと思っています。
Input
入力は以下の形式で与えられる。
N
M
C
a
1
a
2
...
a
N
1行目に、1つの整数
N
,
M
,
C
が空白区切りで与えられる。2行目に
N
つの整数が空白区切りで与えられる。
a
i
は
i
番目の廃材の香りの強さを表す。
Constraints
入力は以下の制約を満たす。
1 ≤
N
≤ 10
5
1 ≤
M
≤ 10
14
1 ≤
C
≤ 10
9
0 ≤
a
i
≤ 10
9
(1 ≤
i
≤
N
)
Output
精度
R
の検出器を使って認識される廃材の香りの総和を
M
以上にしたときの
R
の最小値を出力せよ。
それが不可能な場合は−1を出力せよ。
R
は必ず0以上であり、負の値の精度は存在しない。
Sample Input1
6 25 3
8 5 1 1 2 6
Sample Output1
1
このとき、精度0の検出器を使うと
8 + 5 + 1 + 1 + 2 + 6 = 23　で25以上になりません。
精度1の検出器を使うと
max(8,5-3) + max(8-3,5,1-3) + max(5-3,1,1-3) + max(1-3,1,2-3) + max(1-3,2,6-3) + max(2-3,6)
= 8 + 5 + 2 + 1 + 3 + 6 = 25 で25以上になるので1が正解です。
Sample Input2
4 10 1
1 2 3 4
Sample Output2
0
Sample Input3
4 11 1
1 2 3 4
Sample Output3
-1

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;

long long computeSum(const vector<long long>& a, long long C, int R, long long M) {
    int N = (int)a.size();
    vector<long long> L(N), Rv(N);
    for(int j = 0; j < N; j++){
        L[j]  = a[j] + C * (j+1);     
        Rv[j] = a[j] - C * (j+1);
    }


    vector<long long> leftMax(N), rightMax(N);

    deque<int> dq;

    for(int i = 0; i < N; i++){
        while(!dq.empty() && dq.front() < i - R) {
            dq.pop_front();
        }
        while(!dq.empty() && L[dq.back()] <= L[i]) {
            dq.pop_back();
        }
        dq.push_back(i);
        leftMax[i] = L[dq.front()];
    }

    dq.clear();
    for(int i = N-1; i >= 0; i--){
        while(!dq.empty() && dq.front() > i + R) {
            dq.pop_front();
        }
                while(!dq.empty() && Rv[dq.back()] <= Rv[i]){
            dq.pop_back();
        }
        dq.push_back(i);
        rightMax[i] = Rv[dq.front()];
    }

    long long sumVal = 0;
    for(int i = 0; i < N; i++){
        long long valLeft  = leftMax[i]  - C * (i+1);
        long long valRight = rightMax[i] + C * (i+1);
        long long recognized = max(valLeft, valRight);
        sumVal += recognized;

        if(sumVal >= M) {
            return sumVal; 
        }
    }
    return sumVal;
}

int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    long long N, M, C;
    cin >> N >> M >> C;
    vector<long long> a(N);
    for(int i=0; i<(int)N; i++){
        cin >> a[i];
    }

    {
        long long valMax = computeSum(a, C, (int)N, M);
        if(valMax < M) {
            cout << -1 << "\n";
            return 0;
        }
    }

    int left = 0;
    int right = (int)N; 
    int ans = right;
    while(left <= right){
        int mid = (left + right) / 2;
        long long sumVal = computeSum(a, C, mid, M);
        if(sumVal >= M){
            ans = mid;
            right = mid - 1;
        } else {
            left = mid + 1;
        }
    }
    cout << ans << "\n";
    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 7060
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;

// Функция, которая по заданному R вычисляет суммарный распознанный запах S(R).
// Возвращает -1, если сумма превысила типичные границы 64-битного long long,
// но фактически нам достаточно понять, >= M или нет, так что можно "обрезать".
long long computeSum(const vector<long long>& a, long long C, int R, long long M) {
    // N = размер массива a
    int N = (int)a.size();
    // Приготовим массивы L_j = a_j + C*j и R_j = a_j - C*j
    // (j индексируем с 1, поэтому удобно завести L[1..N], R[1..N])
    // но в C++ вектор с 0-индексом, просто аккуратно будем обращаться
    vector<long long> L(N), Rv(N);
    for(int j = 0; j < N; j++){
        L[j]  = a[j] + C * (j+1);     // (j+1) => индекс j в а есть j+1 "по формуле"
        Rv[j] = a[j] - C * (j+1);
    }

    // Будем находить для каждого i:
    //   leftMax[i] = max(L_j) для j в [i-R, i]
    //   rightMax[i] = max(R_j) для j в [i, i+R]
    // i пробегаем от 1 до N (но в коде это 0..N-1)

    vector<long long> leftMax(N), rightMax(N);

    // 1) Считаем leftMax[i] (скользящее окно по L).
    //    Окно размера (R+1), но фактически оно "динамическое" со сдвигом.
    //    Используем дек, храним в нём кандидатов "j" (индексы), поддерживаем max.
    deque<int> dq;
    // Сначала разогреваем начальное окно для i=0?
    // Но заметим, что для i=0 (то есть i=1 по условию), мы берем j в [1-R, 1].
    // При R>0 индексы j<1 не существуют, так что effectively это просто j=1.
    // Тем не менее можно аккуратно в общем цикле.

    // Идём слева направо: для i от 0 до N-1
    //   Хотим, чтобы в dq были индексы j такие, что j <= i, но j>= i-R.
    //   Перед тем как перейти к i, убираем из головы dq те j, которые вышли из [i-R, i].
    //   Потом добавляем i в dq, выбрасывая "хуже" из хвоста.
    for(int i = 0; i < N; i++){
        // Убираем из головы те, кто выпал из диапазона [i-R, i].
        while(!dq.empty() && dq.front() < i - R) {
            dq.pop_front();
        }
        // Добавляем i в дек, выбросив из хвоста тех, у кого L[..] <= L[i]
        while(!dq.empty() && L[dq.back()] <= L[i]) {
            dq.pop_back();
        }
        dq.push_back(i);
        // Теперь dq.front() - индекс, где L[...] максимально на отрезке [i-R, i].
        leftMax[i] = L[dq.front()];
    }

    // 2) Аналогично считаем rightMax[i] (но идём справа налево).
    dq.clear();
    for(int i = N-1; i >= 0; i--){
        // Убираем тех, кто вышел из [i, i+R] => т.е. индекс > i+R
        while(!dq.empty() && dq.front() > i + R) {
            dq.pop_front();
        }
        // Добавляем i
        while(!dq.empty() && Rv[dq.back()] <= Rv[i]){
            dq.pop_back();
        }
        dq.push_back(i);
        // dq.front() - индекс, где Rv[...] максимум на [i, i+R].
        rightMax[i] = Rv[dq.front()];
    }

    // Теперь считаем суммарно:
    //   recognized_i = max( leftMax[i] - C*(i+1),  rightMax[i] + C*(i+1) )
    //   (т.к. i+1 - это "настоящий" индекс в формуле)
    // суммируем.
    long long sumVal = 0;
    for(int i = 0; i < N; i++){
        long long valLeft  = leftMax[i]  - C * (i+1);
        long long valRight = rightMax[i] + C * (i+1);
        long long recognized = max(valLeft, valRight);

        // recognized может быть отрицательным, если a_j очень маленькие и C большое.
        // Но минимальное может быть и 0, если учесть, что если a_j - ... < 0,
        // всё равно берем максимум по j, возможно где-то есть неотрицательное.
        // Однако по условию мы берём именно max(..), который может оказаться <0,
        // тогда это действительно отрицательный вклад.
        // Здесь не сказано явно "не брать <0", значит берём как есть.

        sumVal += recognized;

        // Чтобы не словить переполнение, если sumVal превысит M достаточно,
        // то можно прервать и вернуть что-то (например sumVal), всё равно это >= M.
        if(sumVal >= M) {
            return sumVal; 
        }
    }
    return sumVal;
}

int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    long long N, M, C;
    cin >> N >> M >> C;
    vector<long long> a(N);
    for(int i=0; i<(int)N; i++){
        cin >> a[i];
    }

    // Проверим, может ли вообще быть >= M при R = N (максимальном).
    // Если и при R=N не набираем, сразу -1.
    // Иначе делаем бинарный поиск в [0..N].
    {
        long long valMax = computeSum(a, C, (int)N, M);
        if(valMax < M) {
            cout << -1 << "\n";
            return 0;
        }
    }

    // Бинарный поиск
    int left = 0;
    int right = (int)N; 
    int ans = right;
    while(left <= right){
        int mid = (left + right) / 2;
        long long sumVal = computeSum(a, C, mid, M);
        if(sumVal >= M){
            ans = mid;
            right = mid - 1;
        } else {
            left = mid + 1;
        }
    }
    cout << ans << "\n";
    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 7060
final_rank: 2

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 1000000000000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 100005

int N = 1;
ll M,C;
ll A[SIZE];
ll max_data[4*SIZE],add_data[4*SIZE];
ll L_max[SIZE],R_max[SIZE];

void init(int first_N){
	while(N < first_N)N *= 2;
}

void add(int left,int right,ll value,int node_id,int node_left,int node_right){

	if(right < node_left || left > node_right){
		//範囲外ならreturn
		return;
	}
	else if(left <= node_left && right >= node_right){ //このノードのカバーしている区間が、更新区間の部分区間である場合

		add_data[node_id] += value; //一様に加える値を加算

		while(node_id != 0){

			node_id = (node_id-1)/2; //下から上に向かって、最小値および最大値更新
			max_data[node_id] = max(max_data[2*node_id+1]+add_data[2*node_id+1],max_data[2*node_id+2]+add_data[2*node_id+2]);
		}
	}else{

		add(left,right,value,2*node_id+1,node_left,(node_left+node_right)/2);
		add(left,right,value,2*node_id+2,(node_left+node_right)/2+1,node_right);
	}
}

ll getMax(int left,int right,int node_id,int node_left,int node_right){
	if(right < node_left || left > node_right)return -BIG_NUM;
	else if(left <= node_left && right >= node_right){
		return max_data[node_id]+add_data[node_id];

	}else{

		ll  left_max  = getMax(left,right,2*node_id+1,node_left,(node_left+node_right)/2);
		ll  right_max = getMax(left,right,2*node_id+2,(node_left+node_right)/2+1,node_right);
		return max(left_max,right_max)+add_data[node_id];
	}
}

int main(){

	int first_N;
	scanf("%d %lld %lld",&first_N,&M,&C);

	ll first_sum = 0;

	for(int i = 0; i < first_N; i++){

		scanf("%lld",&A[i]);
		first_sum += A[i];
	}

	if(first_sum >= M){

		printf("0\n");
		return 0;
	}

	init(first_N);

	int left = 1,right = first_N,mid = (left+right)/2;
	int ans = BIG_NUM;

	//探索範囲は増えるのは、損にならないので範囲の二分探索ができるはず

	while(left <= right){

		for(int i = 0; i <= 2*N-2; i++){
			max_data[i] = 0;
			add_data[i] = 0;
		}

		for(int i = 0; i < first_N; i++){

			add(i,i,A[i],0,0,N-1);
		}

		for(int i = 0; i < first_N; i++){

			L_max[i] = -HUGE_NUM;
		}

		//左から
		for(int i = 0; i < first_N; i++){
			if(i > 0){

				add(max(0,i-mid),i-1,-C,0,0,N-1);
			}
			L_max[i] = getMax(max(0,i-mid),i,0,0,N-1);
		}

		for(int i = 0; i <= 2*N-2; i++){
			max_data[i] = 0;
			add_data[i] = 0;
		}

		for(int i = 0; i < first_N; i++){

			add(i,i,A[i],0,0,N-1);
		}

		ll sum = 0;
		for(int i = 0; i < first_N; i++){

			R_max[i] = -HUGE_NUM;
		}

		//右から
		for(int i = first_N-1; i >= 0; i--){
			if(i < first_N-1){

				add(i+1,min(first_N-1,i+mid),-C,0,0,N-1);
			}
			R_max[i] = getMax(i,min(first_N-1,i+mid),0,0,N-1);
		}

		for(int i = 0; i < first_N; i++){

			sum += max(L_max[i],R_max[i]);
		}

		if(sum >= M){

			ans = mid;
			right = mid-1;

		}else{

			left = mid+1;
		}
		mid = (left+right)/2;
	}

	if(ans == BIG_NUM){

		printf("-1\n");
	}else{

		printf("%d\n",ans);
	}

	return 0;
}
accuracy: 1
time_ms: 2260
memory_kb: 9688
final_rank: 8

code_snippet: #include <iostream>
#include <vector>
using namespace std;

class RangeMax {
public:
	int size_ = 1;
	vector<long long> dat;

	void init(int sz) {
		size_ = 1;
		while (size_ <= sz) size_ *= 2;
		dat.resize(size_ * 2, 0);
	}

	void update(int pos, long long x) {
		pos += size_;
		dat[pos] = x;
		while (pos >= 2) {
			pos >>= 1;
			dat[pos] = max(dat[pos * 2], dat[pos * 2 + 1]);
		}
	}

	long long query_(int l, int r, int a, int b, int u) {
		if (l <= a && b <= r) return dat[u];
		if (r <= a || b <= l) return -(1LL << 60);
		long long v1 = query_(l, r, a, (a + b) / 2, u * 2);
		long long v2 = query_(l, r, (a + b) / 2, b, u * 2 + 1);
		return max(v1, v2);
	}

	long long query(int l, int r) {
		return query_(l, r, 0, size_, 1);
	}
};

long long N, A[1 << 18];
long long M;
long long C;
RangeMax Left;
RangeMax Rigt;

bool solve(int border) {
	long long Sum = 0;

	// Calculate
	for (int i = 1; i <= N; i++) {
		int cl = max(1, i - border);
		int cr = min((int)N, i + border);
		long long val1 = Left.query(cl, i + 1);
		long long val2 = Rigt.query(i, cr + 1);
		val1 -= 1LL * i * C;
		val2 += 1LL * i * C;
		Sum += max(val1, val2);
	}

	// Hantei
	if (Sum >= M) return true;
	return false;
}

int main() {
	// Step 1. Input
	cin >> N >> M >> C;
	for (int i = 1; i <= N; i++) cin >> A[i];

	// Step 2. Init
	Left.init(N + 2);
	Rigt.init(N + 2);
	for (int i = 1; i <= N; i++) Left.update(i, A[i] + 1LL * i * C);
	for (int i = 1; i <= N; i++) Rigt.update(i, A[i] - 1LL * i * C);

	// Step 3. Binary Search
	int dl = 0, dr = N + 1, dm, minx = (1 << 30);
	for (int i = 0; i < 20; i++) {
		dm = (dl + dr) / 2;
		bool ret = solve(dm);
		if (ret == true) { dr = dm; minx = min(minx, dm); }
		else { dl = dm; }
	}

	// Step 4. Output
	if (minx == (1 << 30)) cout << "-1" << endl;
	else cout << minx << endl;
	return 0;
}
accuracy: 1
time_ms: 440
memory_kb: 8120
final_rank: 5

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 1000000000000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 100005

int N = 1;
ll M,C;
ll A[SIZE];
ll max_data[4*SIZE],add_data[4*SIZE];
ll L_max[SIZE],R_max[SIZE];

void init(int first_N){
	while(N < first_N)N *= 2;
}

void add(int left,int right,ll value,int node_id,int node_left,int node_right){

	if(right < node_left || left > node_right){
		//範囲外ならreturn
		return;
	}
	else if(left <= node_left && right >= node_right){ //このノードのカバーしている区間が、更新区間の部分区間である場合

		add_data[node_id] += value; //一様に加える値を加算

		while(node_id != 0){

			node_id = (node_id-1)/2; //下から上に向かって、最小値および最大値更新
			max_data[node_id] = max(max_data[2*node_id+1]+add_data[2*node_id+1],max_data[2*node_id+2]+add_data[2*node_id+2]);
		}
	}else{

		add(left,right,value,2*node_id+1,node_left,(node_left+node_right)/2);
		add(left,right,value,2*node_id+2,(node_left+node_right)/2+1,node_right);
	}
}

ll getMax(int left,int right,int node_id,int node_left,int node_right){
	if(right < node_left || left > node_right)return -BIG_NUM;
	else if(left <= node_left && right >= node_right){
		return max_data[node_id]+add_data[node_id];

	}else{

		ll  left_max  = getMax(left,right,2*node_id+1,node_left,(node_left+node_right)/2);
		ll  right_max = getMax(left,right,2*node_id+2,(node_left+node_right)/2+1,node_right);
		return max(left_max,right_max)+add_data[node_id];
	}
}

int main(){

	int first_N;
	scanf("%d %lld %lld",&first_N,&M,&C);

	ll first_sum = 0;

	for(int i = 0; i < first_N; i++){

		scanf("%lld",&A[i]);
		first_sum += A[i];
	}

	if(first_sum >= M){

		printf("0\n");
		return 0;
	}

	init(first_N);

	int left = 1,right = first_N,mid = (left+right)/2;
	int ans = BIG_NUM;

	//探索範囲は増えるのは、損にならないので範囲の二分探索ができるはず

	while(left <= right){

		for(int i = 0; i <= 2*N-2; i++){
			max_data[i] = 0;
			add_data[i] = 0;
		}

		for(int i = 0; i < first_N; i++){

			add(i,i,A[i],0,0,N-1);
		}

		for(int i = 0; i < first_N; i++){

			L_max[i] = -HUGE_NUM;
		}

		//左から
		for(int i = 0; i < first_N; i++){
			if(i > 0){

				add(max(0,i-mid),i-1,-C,0,0,N-1);
			}
			L_max[i] = getMax(max(0,i-mid),i,0,0,N-1);
		}

		for(int i = 0; i <= 2*N-2; i++){
			max_data[i] = 0;
			add_data[i] = 0;
		}

		for(int i = 0; i < first_N; i++){

			add(i,i,A[i],0,0,N-1);
		}

		ll sum = 0;
		for(int i = 0; i < first_N; i++){

			R_max[i] = -HUGE_NUM;
		}

		//右から
		for(int i = first_N-1; i >= 0; i--){
			if(i < first_N-1){

				add(i+1,min(first_N-1,i+mid),-C,0,0,N-1);
			}
			R_max[i] = getMax(i,min(first_N-1,i+mid),0,0,N-1);
		}

		for(int i = 0; i < first_N; i++){

			sum += max(L_max[i],R_max[i]);
		}

		if(sum >= M){

			ans = mid;
			right = mid-1;

		}else{

			left = mid+1;
		}
		mid = (left+right)/2;
	}

	if(ans == BIG_NUM){

		printf("-1\n");
	}else{

		printf("%d\n",ans);
	}

	return 0;
}
accuracy: 1
time_ms: 2280
memory_kb: 9660
final_rank: 9

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 1000000000000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 100005

int N = 1;
ll M,C;
ll A[SIZE];
ll min_data[4*SIZE],max_data[4*SIZE],add_data[4*SIZE];
ll L_max[SIZE],R_max[SIZE];

void init(int first_N){
	while(N < first_N)N *= 2;
}

void add(int left,int right,ll value,int node_id,int node_left,int node_right){

	if(right < node_left || left > node_right){
		//範囲外ならreturn
		return;
	}
	else if(left <= node_left && right >= node_right){ //このノードのカバーしている区間が、更新区間の部分区間である場合

		add_data[node_id] += value; //一様に加える値を加算

		while(node_id != 0){

			node_id = (node_id-1)/2; //下から上に向かって、最小値および最大値更新
			min_data[node_id] = min(min_data[2*node_id+1]+add_data[2*node_id+1],min_data[2*node_id+2]+add_data[2*node_id+2]);
			max_data[node_id] = max(max_data[2*node_id+1]+add_data[2*node_id+1],max_data[2*node_id+2]+add_data[2*node_id+2]);
		}
	}else{

		add(left,right,value,2*node_id+1,node_left,(node_left+node_right)/2);
		add(left,right,value,2*node_id+2,(node_left+node_right)/2+1,node_right);
	}
}

ll getMax(int left,int right,int node_id,int node_left,int node_right){
	if(right < node_left || left > node_right)return -BIG_NUM;
	else if(left <= node_left && right >= node_right){
		return max_data[node_id]+add_data[node_id];

	}else{

		ll  left_max  = getMax(left,right,2*node_id+1,node_left,(node_left+node_right)/2);
		ll  right_max = getMax(left,right,2*node_id+2,(node_left+node_right)/2+1,node_right);
		return max(left_max,right_max)+add_data[node_id];
	}
}

int main(){

	int first_N;
	scanf("%d %lld %lld",&first_N,&M,&C);

	ll first_sum = 0;

	for(int i = 0; i < first_N; i++){

		scanf("%lld",&A[i]);
		first_sum += A[i];
	}

	if(first_sum >= M){

		printf("0\n");
		return 0;
	}

	init(first_N);

	int left = 1,right = first_N,mid = (left+right)/2;
	int ans = BIG_NUM;

	//探索範囲は増えるのは、損にならないので範囲の二分探索ができるはず

	while(left <= right){

		for(int i = 0; i <= 2*N-2; i++){
			min_data[i] = 0;
			max_data[i] = 0;
			add_data[i] = 0;
		}

		for(int i = 0; i < first_N; i++){

			add(i,i,A[i],0,0,N-1);
		}

		for(int i = 0; i < first_N; i++){

			L_max[i] = -HUGE_NUM;
		}

		//左から
		for(int i = 0; i < first_N; i++){
			if(i > 0){

				add(max(0,i-mid),i-1,-C,0,0,N-1);
			}
			L_max[i] = getMax(max(0,i-mid),i,0,0,N-1);
		}

		for(int i = 0; i <= 2*N-2; i++){
			min_data[i] = 0;
			max_data[i] = 0;
			add_data[i] = 0;
		}

		for(int i = 0; i < first_N; i++){

			add(i,i,A[i],0,0,N-1);
		}

		ll sum = 0;
		for(int i = 0; i < first_N; i++){

			R_max[i] = -HUGE_NUM;
		}

		//右から
		for(int i = first_N-1; i >= 0; i--){
			if(i < first_N-1){

				add(i+1,min(first_N-1,i+mid),-C,0,0,N-1);
			}
			R_max[i] = getMax(i,min(first_N-1,i+mid),0,0,N-1);
		}

		for(int i = 0; i < first_N; i++){

			sum += max(L_max[i],R_max[i]);
		}

		if(sum >= M){

			ans = mid;
			right = mid-1;

		}else{

			left = mid+1;
		}
		mid = (left+right)/2;
	}

	if(ans == BIG_NUM){

		printf("-1\n");
	}else{

		printf("%d\n",ans);
	}

	return 0;
}
accuracy: 1
time_ms: 2560
memory_kb: 11704
final_rank: 10

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 1000000000000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 100005

int N = 1;
ll M,C;
ll A[SIZE];
ll min_data[4*SIZE],max_data[4*SIZE],add_data[4*SIZE];
ll L_max[SIZE],R_max[SIZE];

void init(int first_N){
	while(N < first_N)N *= 2;
}

void add(int left,int right,ll value,int node_id,int node_left,int node_right){

	if(right < node_left || left > node_right){
		//範囲外ならreturn
		return;
	}
	else if(left <= node_left && right >= node_right){ //このノードのカバーしている区間が、更新区間の部分区間である場合

		add_data[node_id] += value; //一様に加える値を加算

		while(node_id != 0){

			node_id = (node_id-1)/2; //下から上に向かって、最小値および最大値更新
			min_data[node_id] = min(min_data[2*node_id+1]+add_data[2*node_id+1],min_data[2*node_id+2]+add_data[2*node_id+2]);
			max_data[node_id] = max(max_data[2*node_id+1]+add_data[2*node_id+1],max_data[2*node_id+2]+add_data[2*node_id+2]);
		}
	}else{

		add(left,right,value,2*node_id+1,node_left,(node_left+node_right)/2);
		add(left,right,value,2*node_id+2,(node_left+node_right)/2+1,node_right);
	}
}

ll getMax(int left,int right,int node_id,int node_left,int node_right){
	if(right < node_left || left > node_right)return -BIG_NUM;
	else if(left <= node_left && right >= node_right){
		return max_data[node_id]+add_data[node_id];

	}else{

		ll  left_max  = getMax(left,right,2*node_id+1,node_left,(node_left+node_right)/2);
		ll  right_max = getMax(left,right,2*node_id+2,(node_left+node_right)/2+1,node_right);
		return max(left_max,right_max)+add_data[node_id];
	}
}

int main(){

	int first_N;
	scanf("%d %lld %lld",&first_N,&M,&C);

	ll first_sum = 0;

	for(int i = 0; i < first_N; i++){

		scanf("%lld",&A[i]);
		first_sum += A[i];
	}

	if(first_sum >= M){

		printf("0\n");
		return 0;
	}

	init(first_N);

	int left = 1,right = first_N,mid = (left+right)/2;
	int ans = BIG_NUM;

	//探索範囲は増えるのは、損にならないので範囲の二分探索ができるはず

	while(left <= right){

		for(int i = 0; i <= 2*N-2; i++){
			min_data[i] = 0;
			max_data[i] = 0;
			add_data[i] = 0;
		}

		for(int i = 0; i < first_N; i++){

			add(i,i,A[i],0,0,N-1);
		}

		for(int i = 0; i < first_N; i++){

			L_max[i] = -HUGE_NUM;
		}

		//左から
		for(int i = 0; i < first_N; i++){
			if(i > 0){

				add(max(0,i-mid),i-1,-C,0,0,N-1);
			}
			L_max[i] = getMax(max(0,i-mid),i,0,0,N-1);
		}

		for(int i = 0; i <= 2*N-2; i++){
			min_data[i] = 0;
			max_data[i] = 0;
			add_data[i] = 0;
		}

		for(int i = 0; i < first_N; i++){

			add(i,i,A[i],0,0,N-1);
		}

		ll sum = 0;
		for(int i = 0; i < first_N; i++){

			R_max[i] = -HUGE_NUM;
		}

		//右から
		for(int i = first_N-1; i >= 0; i--){
			if(i < first_N-1){

				add(i+1,min(first_N-1,i+mid),-C,0,0,N-1);
			}
			R_max[i] = getMax(i,min(first_N-1,i+mid),0,0,N-1);
		}

		for(int i = 0; i < first_N; i++){

			sum += max(L_max[i],R_max[i]);
		}

		if(sum >= M){

			ans = mid;
			right = mid-1;

		}else{

			left = mid+1;
		}
		mid = (left+right)/2;
	}

	if(ans == BIG_NUM){

		printf("-1\n");
	}else{

		printf("%lld\n",ans);
	}

	return 0;
}
accuracy: 1
time_ms: 2560
memory_kb: 11708
final_rank: 11

code_snippet: #include <bits/stdc++.h>

/////////////////////////
// Range Minimum Query //
/////////////////////////

class RangeMaximumQuery {
private:
	std::vector<long long> container_;
	void constructorHelper(const unsigned int array_size)
	{
		unsigned int length{1};
		while (length < array_size)
			length <<= 1;
		container_.resize(2 * length);
	}
	long long getHelper(const int index, const int node_l, const int node_r, const int query_l, const int query_r) const
	{
		if (query_r <= node_l || node_r <= query_l) return 0;
		if (query_l <= node_l && node_r <= query_r) return container_[index];
		const int node_m{(node_l + node_r) >> 1};
		return std::max(getHelper(2 * index, node_l, node_m, query_l, query_r), getHelper(2 * index + 1, node_m, node_r, query_l, query_r));
	}

public:
	RangeMaximumQuery(const unsigned int array_size) { constructorHelper(array_size); }
	// indexは0-indexed
	void update(const int index, const long long assigned)
	{
		auto update_place{(container_.size() >> 1) + index};
		container_[update_place] = assigned;
		while (update_place > 1)
		{
			update_place >>= 1;
			container_[update_place] = std::max(container_[2 * update_place], container_[2 * update_place + 1]);
		}
	}
	// left,rightは0-indexed、[left, right)の半開区間
	long long get(const int left, const int right) const
	{
		return getHelper(1, 0, container_.size() >> 1, left, right);
	}
};

int main()
{
	long long N, M, C;
	scanf("%lld%lld%lld", &N, &M, &C);
	std::vector<long long> smell(N);
	for (auto& e: smell) scanf("%lld", &e);
	RangeMaximumQuery inc(N), dec(N);
	// セグ木内部の値はすべて正
	for (long long i{}; i < N; i++)
		inc.update(i, smell[i] + i * C);
	for (long long i{}; i < N; i++)
		dec.update(i, smell[i] + (N - 1 - i) * C);

	auto condition{[&](int R)
		{
			long long sum{};
			for (long long i{}; i < N; i++)
			{
				sum += std::max(inc.get(std::max(i - R, 0ll), i) - C * i, dec.get(i, std::min(i + R + 1, N)) - C * (N - 1 - i));
				if (sum >= M) return true;
			}
			return sum >= M;
		}
	};
	long long ok{N}, ng{-1};
	while (ok - ng > 1)
	{
		long long mid{(ok + ng) / 2};
		if (condition(mid)) ok = mid;
		else ng = mid;
	}
	if (ok == N) puts("-1");
	else printf("%d\n", ok);

	return 0;
}
accuracy: 1
time_ms: 340
memory_kb: 7896
final_rank: 4

code_snippet: #include <bits/stdc++.h>

/////////////////////////
// Range Minimum Query //
/////////////////////////

class RangeMaximumQuery {
private:
	std::vector<long long> container_;
	void constructorHelper(const unsigned int array_size)
	{
		unsigned int length{1};
		while (length < array_size)
			length <<= 1;
		container_.resize(2 * length);
	}
	long long getHelper(const int index, const int node_l, const int node_r, const int query_l, const int query_r) const
	{
		if (query_r <= node_l || node_r <= query_l) return 0;
		if (query_l <= node_l && node_r <= query_r) return container_[index];
		const int node_m{(node_l + node_r) >> 1};
		return std::max(getHelper(2 * index, node_l, node_m, query_l, query_r), getHelper(2 * index + 1, node_m, node_r, query_l, query_r));
	}

public:
	RangeMaximumQuery(const unsigned int array_size) { constructorHelper(array_size); }
	// indexは0-indexed
	void update(const int index, const int assigned)
	{
		auto update_place{(container_.size() >> 1) + index};
		container_[update_place] = assigned;
		while (update_place > 1)
		{
			update_place >>= 1;
			container_[update_place] = std::max(container_[2 * update_place], container_[2 * update_place + 1]);
		}
	}
	// left,rightは0-indexed、[left, right)の半開区間
	long long get(const int left, const int right) const
	{
		return getHelper(1, 0, container_.size() >> 1, left, right);
	}
};

int main()
{
	long long N, M, C;
	scanf("%lld%lld%lld", &N, &M, &C);
	std::vector<long long> smell(N);
	for (auto& e: smell) scanf("%lld", &e);
	RangeMaximumQuery inc(N), dec(N);
	// セグ木内部の値はすべて正
	for (long long i{}; i < N; i++)
		inc.update(i, smell[i] + i * C);
	for (long long i{}; i < N; i++)
		dec.update(i, smell[i] + (N - 1 - i) * C);

	auto condition{[&](int R)
		{
			long long sum{};
			for (long long i{}; i < N; i++)
			{
				sum += std::max(inc.get(std::max(i - R, 0ll), i) - C * i, dec.get(i, std::min(i + R + 1, N)) - C * (N - 1 - i));
				if (sum >= M) return true;
			}
			return sum >= M;
		}
	};
	long long ok{N}, ng{-1};
	while (ok - ng > 1)
	{
		long long mid{(ok + ng) / 2};
		if (condition(mid)) ok = mid;
		else ng = mid;
	}
	if (ok == N) puts("-1");
	else printf("%d\n", ok);

	return 0;
}
accuracy: 0.42105263157894735
time_ms: 270
memory_kb: 7572
final_rank: 13

code_snippet: #include <bits/stdc++.h>

/////////////////////////
// Range Minimum Query //
/////////////////////////

class RangeMaximumQuery {
private:
	std::vector<long long> container_;
	void constructorHelper(const unsigned int array_size)
	{
		unsigned int length{1};
		while (length < array_size)
			length <<= 1;
		container_.resize(2 * length);
	}
	long long getHelper(const int index, const int node_l, const int node_r, const int query_l, const int query_r) const
	{
		if (query_r <= node_l || node_r <= query_l) return 0;
		if (query_l <= node_l && node_r <= query_r) return container_[index];
		const int node_m{(node_l + node_r) >> 1};
		return std::max(getHelper(2 * index, node_l, node_m, query_l, query_r), getHelper(2 * index + 1, node_m, node_r, query_l, query_r));
	}

public:
	RangeMaximumQuery(const unsigned int array_size) { constructorHelper(array_size); }
	// indexは0-indexed
	void update(const int index, const int assigned)
	{
		auto update_place{(container_.size() >> 1) + index};
		container_[update_place] = assigned;
		while (update_place > 1)
		{
			update_place >>= 1;
			container_[update_place] = std::max(container_[2 * update_place], container_[2 * update_place + 1]);
		}
	}
	// left,rightは0-indexed、[left, right)の半開区間
	long long get(const int left, const int right) const
	{
		return getHelper(1, 0, container_.size() >> 1, left, right);
	}
};

int main()
{
	int N;
	long long M, C;
	scanf("%d%lld%lld", &N, &M, &C);
	std::vector<long long> smell(N);
	for (auto& e: smell) scanf("%lld", &e);
	RangeMaximumQuery inc(N), dec(N);
	// セグ木内部の値はすべて正
	for (int i{}; i < N; i++)
		inc.update(i, smell[i] + i * C);
	for (int i{}; i < N; i++)
		dec.update(i, smell[i] + (N - 1 - i) * C);

	auto condition{[&](int R)
		{
			long long sum{};
			for (int i{}; i < N; i++)
			{
				sum += std::max(inc.get(std::max(i - R, 0), i) - C * i, dec.get(i, std::min(i + R + 1, N)) - C * (N - 1 - i));
				if (sum >= M) return true;
			}
			return sum >= M;
		}
	};
	int ok{N}, ng{-1};
	while (ok - ng > 1)
	{
		int mid{(ok + ng) / 2};
		if (condition(mid)) ok = mid;
		else ng = mid;
	}
	if (ok == N) puts("-1");
	else printf("%d\n", ok);

	return 0;
}
accuracy: 0.42105263157894735
time_ms: 270
memory_kb: 7808
final_rank: 18

code_snippet: #include <bits/stdc++.h>

/////////////////////////
// Range Minimum Query //
/////////////////////////

class RangeMaximumQuery {
private:
	std::vector<long long> container_;
	void constructorHelper(const unsigned int array_size)
	{
		unsigned int length{1};
		while (length < array_size)
			length <<= 1;
		container_.resize(2 * length);
	}
	long long getHelper(const int index, const int node_l, const int node_r, const int query_l, const int query_r) const
	{
		if (query_r <= node_l || node_r <= query_l) return 0;
		if (query_l <= node_l && node_r <= query_r) return container_[index];
		const int node_m{(node_l + node_r) >> 1};
		return std::max(getHelper(2 * index, node_l, node_m, query_l, query_r), getHelper(2 * index + 1, node_m, node_r, query_l, query_r));
	}

public:
	RangeMaximumQuery(const unsigned int array_size) { constructorHelper(array_size); }
	// indexは0-indexed
	void update(const int index, const int assigned)
	{
		auto update_place{(container_.size() >> 1) + index};
		container_[update_place] = assigned;
		while (update_place > 1)
		{
			update_place >>= 1;
			container_[update_place] = std::max(container_[2 * update_place], container_[2 * update_place + 1]);
		}
	}
	// left,rightは0-indexed、[left, right)の半開区間
	long long get(const int left, const int right) const
	{
		return getHelper(1, 0, container_.size() >> 1, left, right);
	}
};

int main()
{
	int N;
	long long M, C;
	scanf("%d%lld%lld", &N, &M, &C);
	std::vector<long long> smell(N);
	for (auto& e: smell) scanf("%lld", &e);
	RangeMaximumQuery inc(N), dec(N);
	// セグ木内部の値はすべて正
	for (int i{}; i < N; i++)
		inc.update(i, smell[i] + i * C);
	for (int i{}; i < N; i++)
		dec.update(i, smell[i] + (N - 1 - i) * C);

	auto condition{[&](int R)
		{
			long long sum{};
			for (int i{}; i < N; i++)
				sum += std::max(inc.get(std::max(i - R, 0), i) - C * i, dec.get(i, std::min(i + R + 1, N)) - C * (N - 1 - i));
			return sum >= M;
		}
	};
	int ok{N}, ng{-1};
	while (ok - ng > 1)
	{
		int mid{(ok + ng) / 2};
		if (condition(mid)) ok = mid;
		else ng = mid;
	}
	if (ok == N) puts("-1");
	else printf("%d\n", ok);

	return 0;
}
accuracy: 0.42105263157894735
time_ms: 260
memory_kb: 7860
final_rank: 19

code_snippet: #include <bits/stdc++.h>

/////////////////////////
// Range Minimum Query //
/////////////////////////

class RangeMaximumQuery {
private:
	std::vector<long long> container_;
	void constructorHelper(const unsigned int array_size)
	{
		unsigned int length{1};
		while (length < array_size)
			length <<= 1;
		container_.resize(2 * length);
	}
	long long getHelper(const int index, const int node_l, const int node_r, const int query_l, const int query_r) const
	{
		if (query_r <= node_l || node_r <= query_l) return 0;
		if (query_l <= node_l && node_r <= query_r) return container_[index];
		const int node_m{(node_l + node_r) >> 1};
		return std::max(getHelper(2 * index, node_l, node_m, query_l, query_r), getHelper(2 * index + 1, node_m, node_r, query_l, query_r));
	}

public:
	RangeMaximumQuery(const unsigned int array_size) { constructorHelper(array_size); }
	// indexは0-indexed
	void update(const int index, const int assigned)
	{
		auto update_place{(container_.size() >> 1) + index};
		container_[update_place] = assigned;
		while (update_place > 1)
		{
			update_place >>= 1;
			container_[update_place] = std::max(container_[2 * update_place], container_[2 * update_place + 1]);
		}
	}
	// left,rightは0-indexed、[left, right)の半開区間
	long long get(const int left, const int right) const
	{
		return getHelper(1, 0, container_.size() >> 1, left, right);
	}
};

int main()
{
	int N;
	long long M, C;
	scanf("%d%lld%lld", &N, &M, &C);
	std::vector<long long> smell(N);
	for (auto& e: smell) scanf("%lld", &e);
	RangeMaximumQuery inc(N), dec(N);
	// セグ木内部の値はすべて正
	for (int i{}; i < N; i++)
		inc.update(i, smell[i] + i * C);
	for (int i{}; i < N; i++)
		dec.update(i, smell[i] + (N - 1 - i) * C);

	auto condition{[&](int R)
		{
			long long sum{};
			for (int i{}; i < N; i++)
				sum += std::max(inc.get(i - R, i) - C * i, dec.get(i, i + R + 1) - C * (N - 1 - i));
			return sum >= M;
		}
	};
	int ok{N}, ng{-1};
	while (ok - ng > 1)
	{
		int mid{(ok + ng) / 2};
		if (condition(mid)) ok = mid;
		else ng = mid;
	}
	if (ok == N) puts("-1");
	else printf("%d\n", ok);

	return 0;
}
accuracy: 0.42105263157894735
time_ms: 250
memory_kb: 7856
final_rank: 17

code_snippet: #include <bits/stdc++.h>

/////////////////////////
// Range Minimum Query //
/////////////////////////

class RangeMaximumQuery {
private:
	std::vector<long long> container_;
	void constructorHelper(const unsigned int array_size)
	{
		unsigned int length{1};
		while (length < array_size)
			length <<= 1;
		container_.resize(2 * length);
	}
	long long getHelper(const int index, const int node_l, const int node_r, const int query_l, const int query_r) const
	{
		if (query_r <= node_l || node_r <= query_l) return 0;
		if (query_l <= node_l && node_r <= query_r) return container_[index];
		const int node_m{(node_l + node_r) >> 1};
		return std::max(getHelper(2 * index, node_l, node_m, query_l, query_r), getHelper(2 * index + 1, node_m, node_r, query_l, query_r));
	}

public:
	RangeMaximumQuery(const unsigned int array_size) { constructorHelper(array_size); }
	RangeMaximumQuery(const std::vector<long long> &array)
	{
		constructorHelper(array.size());
		std::copy(array.begin(), array.end(), container_.begin() + (container_.size() >> 1));
		for (auto i{(container_.size() >> 1) - 1}; i > 0; i--)
			container_[i] = std::max(container_[2 * i], container_[2 * i + 1]);
	}
	// indexは0-indexed
	void update(const int index, const int assigned)
	{
		auto update_place{(container_.size() >> 1) + index};
		container_[update_place] = assigned;
		while (update_place > 1)
		{
			update_place >>= 1;
			container_[update_place] = std::max(container_[2 * update_place], container_[2 * update_place + 1]);
		}
	}
	// left,rightは0-indexed、[left, right)の半開区間
	long long get(const int left, const int right) const
	{
		return getHelper(1, 0, container_.size() >> 1, left, right);
	}
};

int main()
{
	int N;
	long long M, C;
	scanf("%d%lld%lld", &N, &M, &C);
	std::vector<long long> smell(N);
	for (auto& e: smell) scanf("%lld", &e);
	RangeMaximumQuery inc(N), dec(N);
	// セグ木内部の値はすべて正
	for (int i{}; i < N; i++)
		inc.update(i, smell[i] + i * C);
	for (int i{}; i < N; i++)
		dec.update(i, smell[i] + (N - 1 - i) * C);

	auto condition{[&](int R)
		{
			long long sum{};
			for (int i{}; i < N; i++)
				sum += std::max({inc.get(i - R, i) - C * i, smell[i], dec.get(i + 1, i + R + 1) - C * (N - 1 - i)});
			return sum >= M;
		}
	};
	int ok{N}, ng{-1};
	while (ok - ng > 1)
	{
		int mid{(ok + ng) / 2};
		if (condition(mid)) ok = mid;
		else ng = mid;
	}
	if (ok == N) puts("-1");
	else printf("%d\n", ok);

	return 0;
}
accuracy: 0.42105263157894735
time_ms: 260
memory_kb: 7816
final_rank: 15

code_snippet: #include <bits/stdc++.h>

/////////////////////////
// Range Minimum Query //
/////////////////////////

class RangeMaximumQuery {
private:
	std::vector<long long> container_;
	void constructorHelper(const unsigned int array_size)
	{
		unsigned int length{1};
		while (length < array_size)
			length <<= 1;
		container_.resize(2 * length, -(1LL << 55));
	}
	long long getHelper(const int index, const int node_l, const int node_r, const int query_l, const int query_r) const
	{
		if (query_r <= node_l || node_r <= query_l) return -(1LL << 55);
		if (query_l <= node_l && node_r <= query_r) return container_[index];
		const int node_m{(node_l + node_r) >> 1};
		return std::max(getHelper(2 * index, node_l, node_m, query_l, query_r), getHelper(2 * index + 1, node_m, node_r, query_l, query_r));
	}

public:
	RangeMaximumQuery(const unsigned int array_size) { constructorHelper(array_size); }
	RangeMaximumQuery(const std::vector<long long> &array)
	{
		constructorHelper(array.size());
		std::copy(array.begin(), array.end(), container_.begin() + (container_.size() >> 1));
		for (auto i{(container_.size() >> 1) - 1}; i > 0; i--)
			container_[i] = std::max(container_[2 * i], container_[2 * i + 1]);
	}
	// indexは0-indexed
	void update(const int index, const int assigned)
	{
		auto update_place{(container_.size() >> 1) + index};
		container_[update_place] = assigned;
		while (update_place > 1)
		{
			update_place >>= 1;
			container_[update_place] = std::max(container_[2 * update_place], container_[2 * update_place + 1]);
		}
	}
	// left,rightは0-indexed、[left, right)の半開区間
	long long get(const int left, const int right) const
	{
		return getHelper(1, 0, container_.size() >> 1, left, right);
	}
};

int main()
{
	int N;
	long long M, C;
	scanf("%d%lld%lld", &N, &M, &C);
	std::vector<long long> smell(N);
	for (auto& e: smell) scanf("%lld", &e);
	RangeMaximumQuery inc(N), dec(N);
	for (int i{}; i < N; i++)
		inc.update(i, smell[i] + i * C);
	for (int i{}; i < N; i++)
		dec.update(i, smell[i] + (N - 1 - i) * C);

	auto condition{[&](int R)
		{
			long long sum{};
			for (int i{}; i < N; i++)
			{
				sum += std::max(inc.get(i - R, i) - C * i, dec.get(i, i + R + 1) - C * (N - 1 - i));
			}
			return sum >= M;
		}
	};
	int ok{N}, ng{-1};
	while (ok - ng > 1)
	{
		int mid{(ok + ng) / 2};
		if (condition(mid)) ok = mid;
		else ng = mid;
	}
	if (ok == N) puts("-1");
	else printf("%d\n", ok);

	return 0;
}
accuracy: 0.42105263157894735
time_ms: 240
memory_kb: 7880
final_rank: 16

code_snippet: #include <bits/stdc++.h>

/////////////////////////
// Range Minimum Query //
/////////////////////////

class RangeMaximumQuery {
private:
	std::vector<long long> container_;
	void constructorHelper(const unsigned int array_size)
	{
		unsigned int length{1};
		while (length < array_size)
			length <<= 1;
		container_.resize(2 * length, -(1LL << 60));
	}
	long long getHelper(const int index, const int node_l, const int node_r, const int query_l, const int query_r) const
	{
		if (query_r <= node_l || node_r <= query_l) return -(1LL << 60);
		if (query_l <= node_l && node_r <= query_r) return container_[index];
		const int node_m{(node_l + node_r) >> 1};
		return std::max(getHelper(2 * index, node_l, node_m, query_l, query_r), getHelper(2 * index + 1, node_m, node_r, query_l, query_r));
	}

public:
	RangeMaximumQuery(const unsigned int array_size) { constructorHelper(array_size); }
	RangeMaximumQuery(const std::vector<long long> &array)
	{
		constructorHelper(array.size());
		std::copy(array.begin(), array.end(), container_.begin() + (container_.size() >> 1));
		for (auto i{(container_.size() >> 1) - 1}; i > 0; i--)
			container_[i] = std::max(container_[2 * i], container_[2 * i + 1]);
	}
	// indexは0-indexed
	void update(const int index, const int assigned)
	{
		auto update_place{(container_.size() >> 1) + index};
		container_[update_place] = assigned;
		while (update_place > 1)
		{
			update_place >>= 1;
			container_[update_place] = std::max(container_[2 * update_place], container_[2 * update_place + 1]);
		}
	}
	// left,rightは0-indexed、[left, right)の半開区間
	long long get(const int left, const int right) const
	{
		// int change{2};
		// for (unsigned int i{1}; i < container_.size(); i++)
		// {
		// 	printf("%lld ", container_[i]);
		// 	if (i + 1 == change)
		// 	{
		// 		putchar('\n');
		// 		change *= 2;
		// 	}
		// }
		return getHelper(1, 0, container_.size() >> 1, left, right);
	}
};

int main()
{
	int N;
	long long M, C;
	scanf("%d%lld%lld", &N, &M, &C);
	std::vector<long long> smell(N);
	for (auto& e: smell) scanf("%lld", &e);
	RangeMaximumQuery inc(N), dec(N);
	for (int i{}; i < N; i++)
		inc.update(i, smell[i] + i * C);
	for (int i{}; i < N; i++)
		dec.update(i, smell[i] + (N - 1 - i) * C);

	auto condition{[&](int R)
		{
			long long sum{};
			for (int i{}; i < N; i++)
			{
				int left{std::max(i - R, 0)}, right{std::min(i + R, N - 1)};
				sum += std::max(inc.get(left, i) - C * i, dec.get(i, right + 1) - C * (N - 1 - i));
			}
			return sum >= M;
		}
	};
	int ok{N}, ng{-1};
	while (ok - ng > 1)
	{
		int mid{(ok + ng) / 2};
		if (condition(mid)) ok = mid;
		else ng = mid;
	}
	if (ok == N) puts("-1");
	else printf("%d\n", ok);

	return 0;
}
accuracy: 0.42105263157894735
time_ms: 250
memory_kb: 7804
final_rank: 14

code_snippet: #include "bits/stdc++.h"
using namespace std;
using ll = long long;



class SegmentTree {
public:
	SegmentTree() {}
	SegmentTree(ll size) {
		n = 1;
		while (n < size)n *= 2;
		dat.resize(2 * n, 0);
	}
	void update(ll k, ll a) {
		k += n - 1;
		dat[k] = a;
		while (k > 0) {
			k = (k - 1) / 2;
			dat[k] = max(dat[k * 2 + 1], dat[k * 2 + 2]);
		}
	}
	ll query(ll a, ll b) {
		return query_impl(a, b, 0, 0, n);
	}
private:
	ll n;
	vector<ll> dat;

	ll query_impl(ll a, ll b, ll k, ll l, ll r) {
		if (r <= a || b <= l)return 0;
		if (a <= l && r <= b)return dat[k];

		ll vl = query_impl(a, b, k * 2 + 1, l, (l + r) / 2);
		ll vr = query_impl(a, b, k * 2 + 2, (l + r) / 2, r);
		return max(vl, vr);
	}
};


ll N, M, C;
SegmentTree stl, str;

bool judge(ll d) {
	vector<ll> res(N);
	for (ll i = 0; i < N; i++) {
		ll a = stl.query(max(0ll, i - d), i + 1) - C * i;
		ll b = str.query(i, min(N - 1, i + d) + 1) - C * (N - 1 - i);
		res[i] = max(a, b);
	}
	return accumulate(res.begin(), res.end(), 0ll) >= M;
}

int main() {
	cin >> N >> M >> C;
	stl = SegmentTree(N);
	str = SegmentTree(N);
	for (int i = 0; i < N; i++) {
		ll ai;
		cin >> ai;
		stl.update(i, ai + C * i);
		str.update(i, ai + C * (N - 1 - i));
	}

	int l = 0, r = N;
	while (r - l > 1) {
		int mid = (l + r) / 2;
		if (judge(mid))r = mid;
		else l = mid;
	}
	if (r == N && !judge(r)) {
		cout << -1 << endl;
	}
	else {
		if (judge(l))cout << l << endl;
		else cout << r << endl;
	}
	return  0;
}
accuracy: 1
time_ms: 580
memory_kb: 7880
final_rank: 6

code_snippet: #include "bits/stdc++.h"
using namespace std;
using ll = long long;



class SegmentTree {
public:
	SegmentTree() {}
	SegmentTree(ll size) {
		n = 1;
		while (n < size)n *= 2;
		dat.resize(2 * n, 0);
	}
	void update(ll k, ll a) {
		k += n - 1;
		dat[k] = a;
		while (k > 0) {
			k = (k - 1) / 2;
			dat[k] = max(dat[k * 2 + 1], dat[k * 2 + 2]);
		}
	}
	ll query(ll a, ll b) {
		return query_impl(a, b, 0, 0, n);
	}
private:
	ll n;
	vector<ll> dat;

	ll query_impl(ll a, ll b, ll k, ll l, ll r) {
		if (r <= a || b <= l)return 0;
		if (a <= l && r <= b)return dat[k];

		ll vl = query_impl(a, b, k * 2 + 1, l, (l + r) / 2);
		ll vr = query_impl(a, b, k * 2 + 2, (l + r) / 2, r);
		return max(vl, vr);
	}
};


ll N, M, C;
SegmentTree stl, str;

bool judge(ll d) {
	vector<ll> res(N);
	for (ll i = 0; i < N; i++) {
		ll a = stl.query(max(0ll, i - d), i + 1) - C * i;
		ll b = str.query(i, min(N - 1, i + d) + 1) - C * (N - 1 - i);
		res[i] = max(a, b);
	}
	return accumulate(res.begin(), res.end(), 0) >= M;
}

int main() {
	cin >> N >> M >> C;
	stl = SegmentTree(N);
	str = SegmentTree(N);
	for (int i = 0; i < N; i++) {
		ll ai;
		cin >> ai;
		stl.update(i, ai + C * i);
		str.update(i, ai + C * (N - 1 - i));
	}

	int l = 0, r = N;
	while (r - l > 1) {
		int mid = (l + r) / 2;
		if (judge(mid))r = mid;
		else l = mid;
	}
	if (r == N && !judge(r)) {
		cout << -1 << endl;
	}
	else {
		if (judge(l))cout << l << endl;
		else cout << r << endl;
	}
	return  0;
}
accuracy: 0.42105263157894735
time_ms: 310
memory_kb: 7816
final_rank: 20

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define REP(i,n) for(int i=0;i<(int)(n);++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
#define valid(y,x,h,w) (0<=y&&y<h&&0<=x&&x<w)
#define tpl(...) make_tuple(__VA_ARGS__)
const int INF = 0x3f3f3f3f;
const double EPS = 1e-8;
const double PI = acos(-1);
typedef long long ll;
typedef pair<ll,ll> pii;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }
template<class T>ostream&operator<<(ostream &o,const vector<T>&t){o<<'[';FOR(i,t){if(i!=t.begin())o<<',';o<<*i;}return o<<']';}
template<class S,class T>ostream&operator<<(ostream &o,const pair<S,T>&t){return o<<'('<<t.first<<','<<t.second<<')';}
template<int N,class Tp>void output(ostream&,const Tp&){}
template<int N,class Tp,class,class ...Ts>void output(ostream &o,const Tp&t){if(N)o<<',';o<<get<N>(t);output<N+1,Tp,Ts...>(o,t);}
template<class ...Ts>ostream&operator<<(ostream&o,const tuple<Ts...>&t){o<<'(';output<0,tuple<Ts...>,Ts...>(o,t);return o<<')';}
template<class T>void output(T t,char z=10){if(t<0)t=-t,putchar(45);int c[20];
  int k=0;while(t)c[k++]=t%10,t/=10;for(k||(c[k++]=0);k;)putchar(c[--k]^48);putchar(z);}
template<class T>void outputs(T t){output(t);}
template<class S,class ...T>void outputs(S a,T...t){output(a,32);outputs(t...);}
template<class T>void output(T *a,int n){REP(i,n)output(a[i],i!=n-1?',':10);}
template<class T>void output(T *a,int n,int m){REP(i,n)output(a[i],m);}
template<class T>bool input(T &t){int n=1,c;for(t=0;!isdigit(c=getchar())&&~c&&c-45;);
  if(!~c)return 0;for(c-45&&(n=0,t=c^48);isdigit(c=getchar());)t=10*t+c-48;t=n?-t:t;return 1;}
template<class S,class ...T>bool input(S&a,T&...t){input(a);return input(t...);}

ll a[100000];
ll b[100000];

ll t[100000];

int main() {
  ll n;
  ll m,C;
  while(input(n,m,C)) {
    REP(i,n) {
      input(a[i]);
      b[i] = a[i];
    }
    reverse(b,b+n);
    ll low = -1, high = n+1;
    while(low+1<high) {
      ll mid = (low+high)/2;
      deque<pii> D;
      REP(i,n) {
        while(D.size()) {
          pii &p = D.front();
          if (p.second < i-mid) {
            D.pop_front();
          } else break;
        }
        while(D.size()) {
          pii &p = D.back();
          if (p.first - (i-p.second)*C < a[i]) {
            D.pop_back();
          } else break;
        }
        D.push_back(pii(a[i], i));
        pii &p = D.front();
        t[i] = p.first - (i-p.second)*C;
        // REP(j,D.size()) {
        //   assert(D[j].first-(i-D[j].second)*C <= t[i]);
        // }
      }
      // REP(i,n) {
      //   ll tmp = a[i];
      //   for (int j=max(0LL,i-mid); j<=i; ++j) {
      //     chmax(tmp, a[j] - abs(i-j)*C);
      //   }
      //   assert(tmp == t[i]);
      // }      
      D.clear();
      REP(i,n) {
        while(D.size()) {
          pii &p = D.front();
          if (p.second < i-mid) {
            D.pop_front();
          } else break;
        }
        while(D.size()) {
          pii &p = D.back();
          if (p.first - (i-p.second)*C < b[i]) {
            D.pop_back();
          } else break;
        }
        D.push_back(pii(b[i], i));
        pii &p = D.front();
        chmax(t[n-i-1], p.first - (i-p.second)*C);
      }
      ll sum = 0;
      REP(i,n) sum += t[i];
      
      // cout << mid << " " << sum << endl;
      // output(t,n);
      if (sum >= m) {
        high = mid;
      } else {
        low = mid;
      }
    }
    if (high == n+1) {
      cout << -1 << endl;
    } else {
      cout << high << endl;
    }
  
  }
}
accuracy: 1
time_ms: 60
memory_kb: 3520
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define REP(i,n) for(int i=0;i<(int)(n);++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
#define valid(y,x,h,w) (0<=y&&y<h&&0<=x&&x<w)
#define tpl(...) make_tuple(__VA_ARGS__)
const int INF = 0x3f3f3f3f;
const double EPS = 1e-8;
const double PI = acos(-1);
typedef long long ll;
typedef pair<ll,ll> pii;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }
template<class T>ostream&operator<<(ostream &o,const vector<T>&t){o<<'[';FOR(i,t){if(i!=t.begin())o<<',';o<<*i;}return o<<']';}
template<class S,class T>ostream&operator<<(ostream &o,const pair<S,T>&t){return o<<'('<<t.first<<','<<t.second<<')';}
template<int N,class Tp>void output(ostream&,const Tp&){}
template<int N,class Tp,class,class ...Ts>void output(ostream &o,const Tp&t){if(N)o<<',';o<<get<N>(t);output<N+1,Tp,Ts...>(o,t);}
template<class ...Ts>ostream&operator<<(ostream&o,const tuple<Ts...>&t){o<<'(';output<0,tuple<Ts...>,Ts...>(o,t);return o<<')';}
template<class T>void output(T t,char z=10){if(t<0)t=-t,putchar(45);int c[20];
  int k=0;while(t)c[k++]=t%10,t/=10;for(k||(c[k++]=0);k;)putchar(c[--k]^48);putchar(z);}
template<class T>void outputs(T t){output(t);}
template<class S,class ...T>void outputs(S a,T...t){output(a,32);outputs(t...);}
template<class T>void output(T *a,int n){REP(i,n)output(a[i],i!=n-1?',':10);}
template<class T>void output(T *a,int n,int m){REP(i,n)output(a[i],m);}
template<class T>bool input(T &t){int n=1,c;for(t=0;!isdigit(c=getchar())&&~c&&c-45;);
  if(!~c)return 0;for(c-45&&(n=0,t=c^48);isdigit(c=getchar());)t=10*t+c-48;t=n?-t:t;return 1;}
template<class S,class ...T>bool input(S&a,T&...t){input(a);return input(t...);}

ll a[100000];
ll b[100000];

ll t[100000];

int main() {
  ll n;
  ll m,C;
  while(input(n,m,C)) {
    REP(i,n) {
      input(a[i]);
      b[i] = a[i];
    }
    reverse(b,b+n);
    ll low = -1, high = n+1;
    while(low+1<high) {
      ll mid = (low+high)/2;
      deque<pii> D;
      REP(i,n) {
        while(D.size()) {
          pii &p = D.front();
          if (p.second < i-mid) {
            D.pop_front();
          } else break;
        }
        while(D.size()) {
          pii &p = D.back();
          if (p.first - (i-p.second)*C < a[i]) {
            D.pop_back();
          } else break;
        }
        D.push_back(pii(a[i], i));
        pii &p = D.front();
        t[i] = p.first - (i-p.second)*C;
        // REP(j,D.size()) {
        //   assert(D[j].first-(i-D[j].second)*C <= t[i]);
        // }
      }
      // REP(i,n) {
      //   ll tmp = a[i];
      //   for (int j=max(0LL,i-mid); j<=i; ++j) {
      //     chmax(tmp, a[j] - abs(i-j)*C);
      //   }
      //   assert(tmp == t[i]);
      // }      
      D.clear();
      REP(i,n) {
        while(D.size()) {
          pii &p = D.front();
          if (p.second < i-mid) {
            D.pop_front();
          } else if (p.first - (i-p.second)*C < b[i]) {
            D.pop_front();
          } else
            break;
        }
        D.push_back(pii(b[i], i));
        pii &p = D.front();
        chmax(t[n-i-1], p.first - (i-p.second)*C);
      }
      ll sum = 0;
      REP(i,n) sum += t[i];
      
      // cout << mid << " " << sum << endl;
      // output(t,n);
      if (sum >= m) {
        high = mid;
      } else {
        low = mid;
      }
    }
    if (high == n+1) {
      cout << -1 << endl;
    } else {
      cout << high << endl;
    }
  
  }
}
accuracy: 0.7192982456140351
time_ms: 50
memory_kb: 3652
final_rank: 12

code_snippet: #include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<set>
#include<list>
#include<queue>
#include<cmath>
#include<functional>
#include<algorithm>
#include<climits>
#define INF (1<<29)
#define EPS 1e-10
#define rep(i,n) for(int i=0;i<(n);i++)
using namespace std;

#define MAX_SIZE 400000

long long segMax[MAX_SIZE - 1], segAdd[MAX_SIZE - 1];


int n;

//区間[a, b)に値xを加算する.
void add(int a, int b, long long x, int k = 0, int l = 0, int r = n)
{
	if (r <= a || b <= l) return;
	
	if (a <= l && r <= b){
		segAdd[k] += x;
		while (k){
			k = (k - 1) / 2;
			segMax[k] = max(segMax[k * 2 + 1] + segAdd[k * 2 + 1], segMax[k * 2 + 2] + segAdd[k * 2 + 2]);
		}
		return;
	}
	
	add(a, b, x, k * 2 + 1, l, (l + r) / 2);
	add(a, b, x, k * 2 + 2, (l + r) / 2, r);
}

long long getMax(int a, int b, int k = 0, int l = 0, int r = n)
{
	if (r <= a || b <= l) return (LLONG_MIN);
	
	if (a <= l && r <= b) return (segMax[k] + segAdd[k]);
	
	long long left = getMax(a, b, k * 2 + 1, l, (l + r) / 2);
	long long right = getMax(a, b, k * 2 + 2, (l + r) / 2, r);
	
	return (max(left, right) + segAdd[k]);
	
}


int a[100000];
void init(){
	memset(segMax,0,sizeof(segMax));
	memset(segAdd,0,sizeof(segAdd));
	rep(i,n)add(i,i+1,a[i]);
}


long long m;
int c;

long long calc(int r){
	long long s=0;
	for(int i=1;i<n;i++){
		add(i,min(i+r+1,n),-c);
	}
	//cout<<'r'<<r<<endl;
	rep(i,n){
		//rep(i,n)cout<<getMax(i,i+1)<<' ';cout<<endl;
		s+=getMax(max(0,i-r),min(n,i+r+1));
		add(0,i+1,-c);
		add(i+1,min(n,i+r+2),c);
	}
	return s;
}


int main(){
	cin>>n>>m>>c;
	rep(i,n)cin>>a[i];
	int l=-1,r=n;
	while(r-l>1){
		int mid=(l+r)/2;
		init();
		if(calc(mid)<m)l=mid;
		else r=mid;
	}
	if(r==n)r=-1;
	cout<<r<<endl;
	return 0;
}
accuracy: 1
time_ms: 2700
memory_kb: 7820
final_rank: 7