Di fenwick e sottosequenze, parte 2

Sto circa uscendo pazzo da fenwick2.
L’idea di base l’ho capita, la soluzione in O(n^2) sarebbe:

per ogni a[i]
    dp[i] = 1
    per ogni a[j] con j < i
        se a[j] < a[i] dp[i] += dp[j]

A questo punto la soluzione è Σ (dp)
Con un fenwick, la soluzione diventa O(n log n):ordinare l’array tenendo conto di quali sono gli indici originari (poniamo che l’indice originario dell’elemento i sia ind(i)), poi:

update(0, 1)
per ogni a[i] con i da 1 a n - 1
    update(ind(i), query(ind(i) - 1) + 1)

E a questo punto il risultato è query(n)

…solo che questa soluzione fa 10/100 e non ne capisco il motivo, anche controllando delle sequenze generate casualmente (grazie random.org) con la soluzione esponenziale vengono uguali alla soluzione con fenwick. Help!

Di seguito il codice:

#include <bits/stdc++.h>

#define lsb(i) i&(-i)

using namespace std;

const int MOD = 1000000007;

size_t n;
int *ft;


bool cmp(pair<int, int> a, pair<int, int> b)
{
    if (a.first == b.first) return a.second > b.second;

    return a.first < b.first;
}

void update(size_t i, int k)
{
    while (i <= n) {
        ft[i] += k % MOD;
        i += lsb(i);
    }
}

size_t query(size_t i)
{
    int ans = 0;

    while (i > 0) {
        ans += ft[i] % MOD;
        i -= lsb(i);
    }

    return ans % MOD;
}

int main()
{
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    pair<int, int> *a;
    int temp;
    cin >> n;
    a = new pair<int, int>[n];
    ft = new int[n + 1];

    for (size_t i = 0; i < n; i++) cin >> a[i].first, a[i].second = i + 1, ft[i + 1] = 0;

    sort(a, a + n, cmp);
    temp = 1;

    for (size_t i = 0; i < n; i++) {
        if (i != 0 && a[i].first != a[i - 1].first) temp = query(a[i].second - 1) + 1;

        update(a[i].second, temp % MOD);
    }

    cout << query(n) % MOD;
    return 0;
}
1 Mi Piace

Non so se può essere d’aiuto, ma anche io ottenevo solo 10/100 prima di accorgermi che andasse calcolato in modulo 1000000007.

Fai attenzione perché se sommi A % MOD + B % MOD potrebbe darti un risultato maggiore di MOD, e quindi devi fare il modulo anche del risultato della somma.

Io comunque ricordo di aver provato in più modi ma non sono riuscito ad ottenere più di 63 punti per output non corretto, quindi probabilmente sfugge qualcosa anche a me :slight_smile:

Una cosa (dato che forse non ho compreso del tutto il problema), ma se l’input è:
4
4 5 4 5
la risposta è 7?

4 Mi Piace

Sì, sia con la soluzione dinamica sia con il fenwick.
Le sequenze sono:
{4}
{5}
{4}
{5}
{4, 5}
{4, 5}
{4, 5}

Invece di farti quell’enorme if, ti puoi creare un nuovo vettore di indici(uguali in caso di pari numeri) e poi controllare e aggiornare il fenwick dal quel vettore.

Strano, ho fatto girare il tuo programma e mi ha scritto 8

4 Mi Piace

Errore mio! Ho aggiornato il programma poco dopo aver postato (mi sono accorto di aver scritto una castroneria nell’if) e mi sono scordato di aggiornare: il risultato è lo stesso comunque. Aggiorno il primo post.