Cod sursa(job #2822604)

Utilizator lolismekAlex Jerpelea lolismek Data 24 decembrie 2021 14:54:53
Problema Cuburi2 Scor 0
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.48 kb
#include <iostream>
#include <fstream>

#define int long long

using namespace std;

ifstream fin("cuburi2.in");
ofstream fout("cuburi2.out");

const int N = 250010, INF = 1e18 + 1;
int v[N], psum[N], psump[N], ssum[N], ssump[N], poz;

int compute_sum(int n, int x, int y, int target) {
	// pentru x, y, turn_target fixate, avem la dreapta suma: psump[y] - psump[i] - i * (psum[y] - psum[i]);
	// pentru x, y, turn_target fixate, avem la stanga suma: ssump[x] - ssump[i] - (n - i + 1) * (ssum[x] - ssum[i]);
	return (psump[y] - psump[target] - target * (psum[y] - psum[target])) + (ssump[x] - ssump[target] - (n - target + 1) * (ssum[x] - ssum[target]));
}

int bs(int st, int dr, int n, int x, int y) {
	if (st == dr) {
		poz = st;
		return compute_sum(n, x, y, st);
	}
	if (dr == st + 1 && compute_sum(n, x, y, st) <= compute_sum(n, x, y, dr)) {
		poz = st;
		return compute_sum(n, x, y, st);
	}
	if (dr == st + 1 && compute_sum(n, x, y, st) > compute_sum(n, x, y, dr)) {
		poz = dr;
		return compute_sum(n, x, y, dr);
	}

	int mid = (st + dr) / 2;
	if (compute_sum(n, x, y, mid) <= compute_sum(n, x, y, mid + 1) && compute_sum(n, x, y, mid) <= compute_sum(n, x, y, mid - 1)) {
		poz = mid;
		return compute_sum(n, x, y, mid);
	}

	if (compute_sum(n, x, y, mid) <= compute_sum(n, x, y, mid - 1) && compute_sum(n, x, y, mid) >= compute_sum(n, x, y, mid + 1)) bs(mid + 1, dr, n, x, y);
	else bs(st, mid - 1, n, x, y);
}

signed main() {
	int n, q;
	fin >> n >> q;
	for (int i = 1; i <= n; i++) {
		fin >> v[i];
		psum[i] = psum[i - 1] + v[i];
		psump[i] = psump[i - 1] + v[i] * i;
	}
	for (int i = n; i >= 1; i--) {
		ssum[i] = ssum[i + 1] + v[i];
		ssump[i] = ssump[i + 1] + v[i] * (n - i + 1);
	}
	while (q--) {
		int x, y;
		fin >> x >> y;
		int st = x, dr = y;
		// asumandu-ne ca raspunsul mai intai scade, iar apoi creste:
		fout << poz << " " << bs(st, dr, n, x, y) << '\n';
	}
	return 0;
}


/*
	// solutie O(N * Q) - 50puncte: (idee optimizare: cautare binara???)
	while (q--) {
		int x, y;
		fin >> x >> y;
		int min_sum = INF, poz;
		for (int target = x; target <= y; target++) {
			// observam ca valorile au o ordine : pana la un moment dat scad / cresc, iar apoi fac opusul => trebuie sa gasim punctul minim aka cel in care se produce schimbare
			int sum = compute_sum(n, x, y, target);
			cout << sum << " ";
			if (sum < min_sum) {
				min_sum = sum;
				poz = target;
			}
		}
		cout << endl;
		fout << poz << " " << min_sum << '\n';
	}
	*/