Cod sursa(job #3322882)

Utilizator maxtraAlex Deonise maxtra Data 16 noiembrie 2025 08:58:15
Problema Buline Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 4.28 kb
/*
descrierea problemei:
N biletele puse in cerc (dupa N urmeaza 1)
pe fiecare bilet ai:
un numar x (numar de buline)
o culoare: 0 - negru, 1 - alb

x buline albe: numar +x
x buline negre: numar -x

deci transformam biletelele intr un vector circular de numere intregi v[1..N]

cerinta:
gaseste o secv circulara de biletele consecutive pe cerc cu:
suma maxima posibila
si ne mai trebuie:
S = suma maxima
P = pozitia de inceput (1-based)
L = lungimea secventei

daca exista mai multe secvente:
alegem cu P minim
si daca si P este egal, alegem cu L minim

ideea algoritmului:
citim datele: 
x c
c = 1 -> v[i] = +x
c = 0 -> v[i] = -x

sum += v[i] -> suma tuturor numerelor (pentru intreg cercul)

avem un cerc -> maximum subarray circular
pe o linie (nu pe cerc) problema este clasica: subsecventa de suma maxima (SSM)
se rezolva cu Kadane in O(N)
dar aici biletele sunt in cerc:
maximum pe cerc este:
1. o secventa normala (nu trece peste capat) -> maximum subarray linie
2. o secventa care trece peste N -> 1

Kadane simplu: gasesti smax, interval [stMax..drMax]
aplici Kadane peste suma minima -> gasesti smin, interval [stMin..drMin]
calculezi sum = suma tuturor elementelor
compari:
smax (fara swap)
sum - smin (cu wrap)

si alegem varianta care da suma mai mare

!!!Obs
daca toate numerele sunt negative, Kadane-clasic da maximul (cel mai putin negaiv), dar:
smin ~ sum (subsecventa minima este aproape tot vectorul)
sum - smin = 0, dar secventa nu poate fi vida, deci nu ai voie sa iei 0
deci, in cazul "toate <= 0" trebuie sa alegi doar smax (si sa nu iei sum-smin)

pasi cod:
1.
v[] - vector de valori +x sau -x
sum - suma totala a tuturor valorilor
smax - suma maxima de secventa (liniara)
smin - suma minima de secventa
stMax, drMax - capetele secventei de suma maxima (linie)
stMin, drMin - capetele secventei de suma minima
st - inceputul secventei curente in Kadane

2. citirea si prelucrarea datelor
citesti x si t
daca t = 0 (negru), transformi x -> -x
acum v[i] este exact +x sau -x
acumulezi sum

3. Kadane pentru suma maxima (fara cerc)
s = suma secventei care se termina la i
daca e mai bine sa o extinzi, -> s += v[i]
daca nu, incepi una noua de la v[i]
daca s este mai mare decat smax, o salvezi ca solutie

4. Kadane pentru suma minima
[stMax..drMax] - subsecventa cu suma maxima (linie)
[stMin..drMin] - subsecventa cu suma minima (linie)

5. combinarea - facem din linie un cerc
avem: 
suma totala sum
suma maxima liniara smax
suma minima smin

doua candidate:
fara wrap:
suma: smax
inceput: stMax
lungime: drMax - stMax + 1
cu wrap:
suma: sum - smin
inceput: drMin + 1 (urmatorul dupa secventa minima)
lungime: numarul de elemente din afara [stMin..drMin]

L = (n - drMin) + (stMin - 1)

daca smax este mai mare decat sum-smin -> alegem solutia liniara
altfel, alegi solutia pe cerc (wrap)
*/
#include <bits/stdc++.h>

using namespace std;

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

int n, v[200005], smax = INT_MIN, smin = INT_MAX, s, sum, stMax, drMax, st, stMin, drMin;
bool t;
int main() 
{
    fin >> n;
    
    for (int i = 1; i <= n; i++) {
        fin >> v[i] >> t;
        
        if (!t) {
            v[i] *= (-1); // valori negative pentru buline negre
        }
        
        sum += v[i]; // calculez suma totala
    }
    
    s = v[1]; // initializez suma curenta
    stMax = drMax = st = 1; // pozitia secventei maxime
    
    for (int i = 2; i <= n; i++) {
        if (s + v[i] >= v[i]) { // extind secventa curenta 
            s += v[i];
        } else { // incep o noua secventa
            s = v[i];
            st = i;
        }
        
        if (s > smax) { // actualizez suma maxima
            smax = s;
            stMax = st;
            drMax = i;
        }
    }
    
    // analog se face pentru suma minima
    s = v[1]; 
    stMin = st = 1; 
    
    for (int i = 2; i <= n; i++) {
        if (s + v[i] <= v[i]) { 
            s += v[i];
        } else { 
            s = v[i];
            st = i;
        }
        
        if (s < smin) { 
            smin = s;
            stMin = st;
            drMin = i;
        }
    }
    
    // comparam suma maxima obtinuta cu cea care trece prin cerc
    if (smax > sum - smin) {
        fout << smax << " " << stMax << " " << drMax - stMax + 1;
    } else {
        fout << sum - smin << " " << drMin + 1 << " " << stMin - 1 + n - drMin;

    }
    return 0;
}