Cod sursa(job #2087129)

Utilizator Nitu.Catalin1998Ioan Florin Catalin Nitu Nitu.Catalin1998 Data 12 decembrie 2017 22:31:46
Problema Range minimum query Scor 60
Compilator c Status done
Runda Arhiva educationala Marime 3.65 kb
/**
https://www.hackerearth.com/practice/data-structures/advanced-data-structures/segment-trees/tutorial/
http://www.geeksforgeeks.org/segment-tree-set-1-range-minimum-query/
*/

#include <stdio.h>
#include <stdlib.h>

void build(int* tree, int a[], int node, int start, int end)
{
    if(start == end)
    {
        // Leaf node will have a single element
        tree[node] = a[start];
    }
    else
    {
        int mid = (start + end) / 2;
        // Recurse on the left child
        build(tree, a, 2 * node + 1, start, mid);
        // Recurse on the right child
        build(tree, a, 2 * node + 2, mid + 1, end);
        // Internal node will have the minimum of both of its children
        tree[node] = tree[2 * node + 1] < tree[2 * node + 2] ?
                     tree[2 * node + 1] : tree[2 * node + 2];
    }
}

int* createSegmentTree(int a[], int n)
{
    int* segmentTree = (int*) malloc((3 * n) * sizeof(int));
    build(segmentTree, a, 0, 0, n - 1);
    return segmentTree;
}

void destroySegmentTree(int* tree)
{
    free(tree);
}

void update(int* tree, int a[], int node, int start, int end, int idx, int val)
{
    if(start == end)
    {
        // Leaf node
        a[idx] += val;
        tree[node] += val;
    }
    else
    {
        int mid = (start + end) / 2;
        if(start <= idx && idx <= mid)
        {
            // If idx is in the left child, recurse on the left child
            update(tree, a, 2 * node + 1, start, mid, idx, val);
        }
        else
        {
            // if idx is in the right child, recurse on the right child
            update(tree, a, 2 * node + 2, mid + 1, end, idx, val);
        }
        // Internal node will have the minimum of both of its children
        tree[node] = tree[2 * node + 1] < tree[2 * node + 2] ?
                     tree[2 * node + 1] : tree[2 * node + 2];
    }
}

void updateValue(int* tree, int a[], int n, int i, int val)
{
    int diff = val - a[i];
    a[i] = diff;
    update(tree, a, 0, 0, n - 1, i, diff);
}

int query(int* tree, int node, int start, int end, int l, int r)
{
    if(r < start || end < l)
    {
        // range represented by a node is completely outside the given range
        //return 0;
        return 1000001;
    }
    if(l <= start && end <= r)
    {
        // range represented by a node is completely inside the given range
        return tree[node];
    }
    // range represented by a node is partially inside and partially outside
    // the given range
    int mid = (start + end) / 2;
    int p1 = query(tree, 2 * node + 1, start, mid, l, r);
    int p2 = query(tree, 2 * node + 2, mid + 1, end, l, r);
    return (p1 < p2 ? p1 : p2);
}

int queryRange(int* tree, int n, int l, int r)
{
    return query(tree, 0, 0, n - 1, l, r);
}

int main()
{
/**
    int a[] = {1, 5, 2, 4, 3};
    int n = sizeof(a) / sizeof(a[0]);

    int* tree = createSegmentTree(a, n);
    printf("%d\n", queryRange(tree, n, 0, 4));
    printf("%d\n", queryRange(tree, n, 0, 2));
    printf("%d\n", queryRange(tree, n, 2, 4));

    updateValue(tree, a, n, 4, 1); // pos than value
    printf("%d\n", queryRange(tree, n, 3, 4));

    destroySegmentTree(tree);
    return 0;
*/
    int n, m;
    FILE* fin = fopen("rmq.in", "r");
    FILE* fout = fopen("rmq.out", "w");
    fscanf(fin, "%d", &n);
    fscanf(fin, "%d", &m);
    int* a = (int*) malloc(n * sizeof(int));
    for(int i = 0; i < n; i++)
    {
        fscanf(fin, "%d", &a[i]);
    }
    int* tree = createSegmentTree(a, n);
    int s, d;
    for(int i = 0; i < m; i++)
    {
        fscanf(fin, "%d", &s);
        fscanf(fin, "%d", &d);
        fprintf(fout, "%d\n", queryRange(tree, n, s - 1, d - 1));
    }

    free(a);
    destroySegmentTree(tree);
    return 0;
}