Cod sursa(job #2555900)

Utilizator memecoinMeme Coin memecoin Data 24 februarie 2020 15:18:49
Problema SequenceQuery Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.98 kb
#include <fstream>
#include <iomanip>
#include <string>
#include <stdio.h>
#include <vector>
#include <algorithm>
#include <math.h>
#include <set>
#include <map>
#include <string.h>
#include <queue>
#include <stack>

#define INF 0x3f3f3f3f

using namespace std;

#ifdef DEBUG
string name = "data";
#else
string name = "sequencequery";
#endif

ifstream fin(name + ".in");
ofstream fout(name + ".out");

#define MAXN 262148

struct Node {
    int64_t beginning;
    int64_t contained;
    int64_t ending;
    int64_t sum;
    
    int64_t best() {
        return max(max(beginning, contained), ending);
    }
};

Node mergeNodes(Node left, Node right) {
    int64_t beginning = max(left.beginning, left.sum + right.beginning);
    
    int64_t ending = max(right.ending, left.ending + right.sum);
    
    int64_t contained = max(max(max(max(left.contained, right.contained), beginning), ending), left.ending + right.beginning);
    
    int64_t sum = -INF;
    
    if (left.sum != -INF && right.sum != -INF) {
        sum = left.sum + right.sum;
    }
    
    return {beginning, contained, ending , sum};
}

Node aint[MAXN];
int n, q;

struct Interval {
    int a;
    int b;
    
    bool equals(Interval &other) {
        return a == other.a && b == other.b;
    }

    bool contains(Interval &other) {
        return other.a >= a && other.b <= b;
    }
    
    bool isDisjoint(Interval &other) {
        return b < other.a || a > other.b;
    }
    
    bool isUnitLength() {
        return a == b;
    }
    
    pair<Interval, Interval> splitAtMidPoint() {
        int mid = (a + b) / 2;
        return {{a, mid}, {mid + 1, b}};
    }
};

Node update(Interval q, Interval window, int node, int x) {
    if (q.isDisjoint(window)) {
        return aint[node];
    }
    
    if (window.isUnitLength()) {
        aint[node] = {x, x, x, x};
        return aint[node];
    }
    
    auto split = window.splitAtMidPoint();
    
    auto left = update(q, split.first, node * 2, x);
    auto right = update(q, split.second, node * 2 + 1, x);
    
    aint[node] = mergeNodes(left, right);
    
    return aint[node];
}

void update(int i, int x) {
    update({i, i}, {1,n}, 1, x);
}

Node query(Interval q, Interval window, int node) {
    if (q.isDisjoint(window)) {
        return {-INF, -INF, -INF, -INF};
    }
    
    if (q.contains(window)) {
        return aint[node];
    }
    
    auto split = window.splitAtMidPoint();
    
    auto left = query(q, split.first, node * 2);
    auto right = query(q, split.second, node * 2 + 1);
    
    return mergeNodes(left, right);
}

int64_t query(int a, int b) {
    auto q = query({a,b}, {1,n}, 1);
    return q.best();
}

int main() {
    
    fin >> n >> q;
    
    for (int i = 1; i <= 2 * n; ++i) {
        aint[i] = {-INF, -INF, -INF, -INF};
    }
    
    for (int i = 1; i <= n; ++i) {
        int x;
        fin >> x;
        update(i, x);
    }
    
    for (int i = 0; i < q; ++i) {
        int x, y;
        fin >> x >> y;
        fout << query(x, y) << "\n";
    }
    
    return 0;
}