Cod sursa(job #466272)

Utilizator bogdan2412Bogdan-Cristian Tataroiu bogdan2412 Data 26 iunie 2010 12:43:44
Problema Numarare Scor Ascuns
Compilator cpp Status done
Runda Marime 2.35 kb
#include <cstdio>
#include <cassert>
#include <algorithm>
#include <vector>

using namespace std;

#define MAXN 100000
#define MAXV 100000
#define MAXT 524288

int N, x[MAXN], first[MAXN];
vector<int> M[2 * MAXV + 1];
int p[2 * MAXV + 1], aint[MAXT];

#define AINTCOMMON int lc = (n << 1), rc = (lc + 1), m = (l + r) >> 1

inline void buildTree(int n, int l, int r) {
    if (l == r) {
        aint[n] = first[l];
        return;
    }
    AINTCOMMON;

    buildTree(lc, l, m);
    buildTree(rc, m + 1, r);
    aint[n] = max(aint[lc], aint[rc]);
}

int QL, QR;
inline int query(int n, int l, int r) {
    if (QL <= l && r <= QR) {
        return aint[n];
    }

    int rez = -1;
    AINTCOMMON;
    if (QL <= m) {
        rez = max(rez, query(lc, l, m));
    }
    if (QR > m) {
        rez = max(rez, query(rc, m + 1, r));
    }
    return rez;
}

int main() {
    freopen("numarare.in", "rt", stdin);
#ifndef DEBUG
    freopen("numarare.out", "wt", stdout);
#endif

    assert(scanf("%d", &N) == 1);
    assert(1 <= N && N <= MAXN);

    int MIN = 0x3f3f3f3f, MAX = -0x3f3f3f3f;
    for (int i = 0; i < N; i++) {
        assert(scanf("%d", x + i) == 1);
        assert(-MAXV <= x[i] && x[i] <= MAXV);
        x[i] += MAXV;
        MIN = min(MIN, x[i]);
        MAX = max(MAX, x[i]);
        M[x[i]].push_back(i);
    }
    for (int i = 0; i <= MAXV * 2; i++) {
        M[i].push_back(N);
    }

    int NR = 0;
    for (int SUM = MIN * 2; SUM <= MAX * 2; SUM++) {
        for (int i = 0; i <= MAXV * 2; i++) {
            p[i] = 0;
        }
        for (int i = 0; i < N; i++) {
            if (x[i] > SUM) {
                first[i] = N;
                continue;
            }

            for (; M[SUM - x[i]][p[SUM - x[i]]] <= i; p[SUM - x[i]] += 1);
            first[i] = M[SUM - x[i]][p[SUM - x[i]]];
        }
        buildTree(1, 0, N - 1);

        for (int i = 0; i < N; i++) {
            vector<int> :: iterator it;
            for (it = M[SUM - x[i]].begin(); it != M[SUM - x[i]].end(); it++) {
                if (*it <= i || *it == N) {
                    continue;
                }
                if ((*it - i + 1) % 2 != 0) {
                    continue;
                }

                QL = i; QR = (i + *it) / 2;
                if (query(1, 0, N - 1) <= *it) {
                    NR += 1;
                }
            }
        }
    }

    printf("%d\n", NR);
    return 0;
}