Cod sursa(job #2756550)

Utilizator NeacsuMihaiNeacsu Mihai NeacsuMihai Data 1 iunie 2021 13:05:20
Problema SequenceQuery Scor 0
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.26 kb
#include <iostream>
#include <fstream>

#define NMAX 100000

using namespace std;

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

struct element{
    long long maxIndSum; //max independent de unde se afla
    long long leftSum, leftSize;
    long long rightSum, rightSize;
};

int X, Y;
int v[NMAX + 1];
element tree[4 * NMAX + 1];

element rezultat(element A, element B, int dim1, int dim2){
    element rez;

    rez.maxIndSum = max(A.maxIndSum, B.maxIndSum);

    if(A.rightSum > 0 && B.leftSum > 0){
        //cel din mijloc devine un candidat pt suma independenta
        rez.maxIndSum = max(rez.maxIndSum, A.rightSum + B.leftSum);
    }

    rez.leftSize = A.leftSize;
    rez.leftSum = A.leftSum;

    rez.rightSize = B.rightSize;
    rez.rightSum = B.rightSum;

    if(A.leftSize == dim1){
        //pot sa adaug si B.lefttSize
        if(B.leftSum > 0){
            rez.leftSum = A.leftSum + B.leftSum;
            rez.leftSize = A.leftSize + B.leftSize;
        }
    }

    if(B.rightSize == dim2){
        //pot sa adaug si A.rightSize
        if(A.rightSum > 0){
            rez.rightSum = B.rightSum + A.rightSum;
            rez.rightSize = B.rightSize + A.rightSize;
        }
    }

    return rez;
}

void buildArbore(int node, int left, int right){
    if(left == right){
        tree[node].leftSize = 1;
        tree[node].leftSum = v[left];

        tree[node].rightSize = 1;
        tree[node].rightSum = v[left];

        tree[node].maxIndSum = v[left];
        return;
    }

    int mid = left + (right - left) / 2;

    buildArbore(node * 2, left, mid);
    buildArbore(node * 2 + 1, mid + 1, right);

    tree[node] = rezultat(tree[node * 2], tree[node * 2 + 1], mid - left + 1, right - mid);
}

element query(int node, int left, int right){
    if(X <= left && right <= Y){
        return tree[node];
    }

    int mid = left + (right - left) / 2;

    element aux1, aux2;
    int OK1 = 0, OK2 = 0;
    if(X <= mid){
        //e relevant si fiul din stanga
        aux1 = query(node * 2, left, mid);
        OK1 = 1;
    }
    if(mid + 1 <= Y){
        //e relevant si fiul din dreapta
        aux2 = query(node * 2 + 1, mid + 1, right);
        OK2 = 1;
    }

    if(OK1 == 1 && OK2 == 1){
        return rezultat(aux1, aux2, mid - left + 1, right - mid); //daca le am pe ambele
    }
    else if(OK1 == 1){
        return aux1;
    }
    else {
        return aux2;
    }
}

int main()
{
    /*
    //testez functia rezultat();
    element A;
    A.leftSize = 3;
    A.rightSize = 3;
    A.maxIndSum = 30;
    A.leftSum = 30;
    A.rightSum = 30;

    element B;
    B.leftSize = 1;
    B.rightSize = 2;
    B.maxIndSum = 10;
    B.leftSum = 3;
    B.rightSum = 9;

    element AUB;
    AUB = rezultat(A, B, 3, 7);

    cout << AUB.leftSize << "\n" << AUB.rightSize << "\n" << AUB.maxIndSum << "\n" << AUB.leftSum << "\n" << AUB.rightSum;
    */



    int N, M;
    fin >> N >> M;

    for(int i = 1; i <= N; i++){
        fin >> v[i];
    }

    buildArbore(1, 1, N);


    for(int q = 1; q <= M; q++){
        fin >> X >> Y;

        element aux = query(1, 1, N);
        fout << aux.maxIndSum << "\n";
    }

    return 0;
}