Cod sursa(job #1712119)

Utilizator AlexandruValeanuAlexandru Valeanu AlexandruValeanu Data 2 iunie 2016 02:25:21
Problema Pq Scor 100
Compilator cpp Status done
Runda Arhiva ICPC Marime 3.1 kb
#include <bits/stdc++.h>

using namespace std;

///---------------------------------------------------
const int BUFFER_SIZE = (1 << 16);
char buffer[BUFFER_SIZE];
int position = BUFFER_SIZE;

inline char getChar()
{
    if ( position == BUFFER_SIZE )
    {
        position = 0;
        fread(buffer, BUFFER_SIZE, 1, stdin);
    }

    return buffer[position++];
}

inline int getInt()
{
    register int a = 0;
    char ch;
    int sgn = 1;

    do
    {
        ch = getChar();

    } while ( !isdigit(ch) && ch != '-' );

    if ( ch == '-' )
    {
        sgn = -1;
        ch = getChar();
    }

    do
    {
        a = (a << 3) + (a << 1) + ch - '0';
        ch = getChar();

    } while ( isdigit(ch) );

    return a * sgn;
}

///---------------------------------------------------

constexpr int INF = numeric_limits<int>::min();
constexpr int MAX_N = 20 * 100000;

class Node
{
public:

    int key;
    int l, r;

    Node() : key{INF}, l{-1}, r{-1} {
    }

    Node(int k) : key{k}, l{-1}, r{-1} {
    }

    Node(const Node &rhs) : key{rhs.key}, l{rhs.l}, r{rhs.r} {
    }
};

Node roots[MAX_N];

int createNode()
{
    static int totalNodes = 0;
    return totalNodes++;
}

int build(int l, int r)
{
    int new_root = createNode();

    if (l != r)
    {
        int m = (l + r) / 2;

        roots[new_root].l = build(l, m);
        roots[new_root].r = build(m + 1, r);
    }

    return new_root;
}

int update(int old_root, int l, int r, int pos, int key)
{
    assert(old_root >= 0);

    int new_root = createNode();
    roots[new_root] = roots[old_root];

    if (l == r)
        roots[new_root].key = key;
    else
    {
        int m = (l + r) / 2;

        if (pos <= m)
            roots[new_root].l = update(roots[old_root].l, l, m, pos, key);
        else
            roots[new_root].r = update(roots[old_root].r, m + 1, r, pos, key);

        roots[new_root].key = max(roots[roots[new_root].l].key, roots[roots[new_root].r].key);
    }

    return new_root;
}

int query(int T, int l, int r, int st_q, int dr_q)
{
    assert(T >= 0);

    if (st_q <= l && r <= dr_q)
        return roots[T].key;

    int m = (l + r) / 2;
    int sol = INF;

    if (st_q <= m)
        sol = max(sol, query(roots[T].l, l, m, st_q, dr_q));

    if (m < dr_q)
        sol = max(sol, query(roots[T].r, m + 1, r, st_q, dr_q));

    return sol;
}

int main()
{
    freopen("pq.in", "r", stdin);
    freopen("pq.out", "w", stdout);

    int N, M;
    N = getInt();
    M = getInt();

    int *A = new int[N + 1];

    for (int i = 1; i <= N; ++i)
        A[i] = getInt();

    int *trees = new int[N + 1];
    trees[0] = build(1, N);

    map<int,int> Index;

    for (int i = 1; i <= N; ++i)
    {
        int pos = Index[ A[i] ];

        if (pos == 0)
            trees[i] = trees[i - 1];
        else
            trees[i] = update(trees[i - 1], 1, N, pos, i - pos);

        Index[ A[i] ] = i;
    }

    while (M--)
    {
        int l, r;
        l = getInt();
        r = getInt();

        int ans = query(trees[r], 1, N, l, r);

        if (ans == INF)
           printf("%d\n", -1);
        else
            printf("%d\n", ans);
    }

    return 0;
}