Submission #1264633

#TimeUsernameProblemLanguageResultExecution timeMemory
1264633jbarejaDungeon 3 (JOI21_ho_t5)C++20
11 / 100
4094 ms11328 KiB
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using PII = pair<int, int>;
#define rep(i, p, k) for (int i(p); i<(k); i++)
#define per(i, p, k) for (int i(p); i>(k); i--)
#define st first
#define nd second
#define pb push_back
#define sz(x) (int)(x).size()

constexpr bool dbg = 0;
#define DEBUG if constexpr(dbg)
#define NODEBUG if constexpr(!dbg)
#define DC DEBUG cerr

struct SegTreeSum {
	vector<ll> values;
	int base = 1;
	ll NEUTRAL = 0;

	void Init(vector<int>& vec) {
		int n = sz(vec);
		while (base <= n) base *= 2;
		values.assign(base * 2, NEUTRAL);
		rep(i, 0, n) values[base + i] = vec[i];
		per(i, base-1, 0) values[i] = values[i*2] + values[i*2+1];
	}

	ll Sum(int l, int r) {
		if (r < l) return NEUTRAL;
		l += base - 1;
		r += base + 1;
		ll ans = NEUTRAL;
		while (l/2 != r/2) {
			if (l % 2 == 0) ans += values[l+1];
			if (r % 2 != 0) ans += values[r-1];
			l /= 2, r /= 2;
		}
		return ans;
	}
};

struct SegTreeMax {
	vector<int> values;
	int base = 1;
	int NEUTRAL = INT_MIN;

	void Init(vector<int>& vec) {
		int n = sz(vec);
		while (base <= n) base *= 2;
		values.assign(base * 2, NEUTRAL);
		rep(i, 0, n) values[base + i] = vec[i];
		per(i, base-1, 0) values[i] = max(values[i*2], values[i*2+1]);
	}

	int Max(int l, int r) {
		l += base - 1;
		r += base + 1;
		int ans = NEUTRAL;
		while (l/2 != r/2) {
			if (l % 2 == 0) ans = max(ans, values[l+1]);
			if (r % 2 != 0) ans = max(ans, values[r-1]);
			l /= 2, r /= 2;
		}
		return ans;
	}
};

struct SegTreeMin {
	vector<PII> values;
	int base = 1;
	PII NEUTRAL = { INT_MAX, -1 };

	PII Merge(PII a, PII b) {
		return min(a, b);
	}

	void Init(vector<int>& vec) {
		int n = sz(vec);
		while (base <= n) base *= 2;
		values.assign(base * 2, NEUTRAL);
		rep(i, 0, n) values[base + i] = { vec[i], i };
		per(i, base-1, 0) values[i] = min(values[i*2], values[i*2+1]);
	}

	PII Min(int l, int r) {
		// DC << "Min(" << l << "," << r << ") = ";
		l += base - 1;
		r += base + 1;
		PII ans = NEUTRAL;
		while (l/2 != r/2) {
			if (l % 2 == 0) ans = Merge(ans, values[l+1]);
			if (r % 2 != 0) ans = Merge(ans, values[r-1]);
			l /= 2, r /= 2;
		}
		// DC << "(" << ans.st << "," << ans.nd << ")\n";
		return ans;
	}
};

struct SegTreeLinearFunction {
	vector<PII> values;
	int base = 1;
	PII NEUTRAL = { 0, 0 };

	PII Merge(PII a, PII b) {
		return { a.st + b.st, a.nd + b.nd };
	}

	void Init(int n) {
		while (base <= n) base *= 2;
		values.assign(base * 2, NEUTRAL);
	}

	void Set(int i, int a, int b) {
		i += base;
		values[i] = { a, b };
		while (i / 2) {
			i /= 2;
			values[i] = Merge(values[i*2], values[i*2+1]);
		}
	}

	PII Sum(int l, int r) {
		l += base - 1;
		r += base + 1;
		PII ans = NEUTRAL;
		while (l/2 != r/2) {
			if (l % 2 == 0) ans = Merge(ans, values[l+1]);
			if (r % 2 != 0) ans = Merge(ans, values[r-1]);
			l /= 2, r /= 2;
		}
		return ans;
	}
};

int n; // liczba odcinków między stacjami
int q; // liczba zapytań

vector<int> A; // A[i] - odległość między stacjami i oraz i+1
vector<int> B; // B[i] - cena paliw na i-tej stacji (nie ma ceny n+1 stacji)

SegTreeMax tree_max_dist;
SegTreeMin tree_min_cost;
vector<ll> pref; // pref[i] - dystans od 1 do i

vector<int> dl; // dl[i] - najbliższa tańsza stacja po lewej (indeks)
vector<int> dr; // dr[i] - najbliższa tańsza stacja po prawej (indeks)

void calculate_dl() {
	stack<PII> S; // < wartość, indeks >
	rep(i, 1, n+1) {
		while (!S.empty() && S.top().st >= B[i]) S.pop();
		if (sz(S)) dl[i] = S.top().nd;
		else dl[i] = INT_MAX;
		S.push({B[i], i});
	}
	S = {};
	DEBUG {
		// cerr << '\n';
		// rep(i, 1, n+1) DC << B[i] << ' ';
		// cerr << '\n';
		// rep(i, 1, n+1) {
		// 	if (dl[i] != INT_MAX) cerr << dl[i] << ' ';
		// 	else cerr << "- ";
		// }
		// cerr << '\n';
	}
}

void calculate_dr() {
	stack<PII> S; // < wartość, indeks >
	per(i, n, 0) {
		while (!S.empty() && S.top().st >= B[i]) S.pop();
		if (sz(S)) dr[i] = S.top().nd;
		else dr[i] = INT_MAX;
		S.push({B[i], i});
	}
	S = {};
	DEBUG {
		// cerr << '\n';
		// rep(i, 1, n+1) DC << B[i] << ' ';
		// cerr << '\n';
		// rep(i, 1, n+1) {
		// 	if (dr[i] != INT_MAX) cerr << dr[i] << ' ';
		// 	else cerr << "- ";
		// }
		// cerr << '\n';
	}
}

ll dist(int l, int r) {
	if (r <= l) return 0;
	return pref[r] - pref[l];
}

ll answer(int l, int r, ll u) {
	ll ans = 0;
	int i = l;
	ll u_now = 0;
	while (i < r) {
		DC << "\n=> jestem w " << i << ", u_now = " << u_now << '\n';
		int low = i+1, high = r;
		while (low < high) {
			int mid = (low + high + 1) / 2;
			if (dist(i, mid) <= u) low = mid;
			else high = mid-1;
		}
		int j = low;

		DC << "najdalej mogę dojechać do " << j << " dist = " << dist(i, j) << '\n';
		int k = dr[i];
		DC << "następna tańsza stacja jest w " << k << "\n";
		if (k > j) {
			if (j == r) {
				DC << "kupuję " << (dist(i,j) - u_now) << " za " << (dist(i,j) - u_now) * B[i] << '\n';
				ll temp = dist(i,j);
				ans += (temp - u_now) * B[i];
				u_now = temp;
			}
			else {
				DC << "kupuję " << (u - u_now) << " za " << (u - u_now) * B[i] << '\n';
				ans += (u - u_now) * B[i];
				u_now = u;
			}
		}
		else {
			ll temp = dist(i, k);
			if (temp > u_now) {
				DC << "kupuję " << (dist(i,k) - u_now) << " za " << (dist(i,k) - u_now) * B[i] << '\n';
				ans += (temp - u_now) * B[i];
				u_now = temp;
			}
		}
		u_now -= A[i];
		i++;
	}
	return ans;
}

int main() {
	NODEBUG { ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); }

	cin >> n >> q;
	A.assign(n+1, 0);
	B.assign(n+1, 0);
	dr.assign(n+1, 0);
	dl.assign(n+1, 0);
	pref.assign(n+7, 0);
	rep(i, 1, n+1) {
		cin >> A[i];
		pref[i+1] = A[i] + pref[i];
	}
	rep(i, 1, n+1) cin >> B[i];
	tree_max_dist.Init(A);
	tree_min_cost.Init(B);

	// calculate_dl();
	calculate_dr();

	rep(i, 0, q) {
		int l, r; ll u;
		cin >> l >> r >> u;

		if (tree_max_dist.Max(l, r-1) > u) {
			cout << "-1\n";
			continue;
		}

		cout << answer(l, r, u) << '\n';
	}
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...