Cod sursa(job #988782)

Utilizator florin.elfusFlorin Elfus florin.elfus Data 23 august 2013 21:07:00
Problema Energii Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.9 kb
//Kterink!
 
#include <stdio.h>
#include <algorithm>
#include <string.h>
#define NMAX 1024
#define MOD 9901
 
using namespace std;
 
int x[NMAX], sortedX[NMAX];
 
struct query
{
    int num, val;
    query ()
    {
        num = 0; val = 0;
    }
} arb[4 * NMAX + 69]; //Acest numar ma excita serios
 
query arbQuery(int st, int dr, int nod, int wantedLeft, int wantedRight)
{
    query ans, now;
     
    if (wantedLeft > wantedRight)
        return ans;
     
    //Verific ca intervalul curent [st, dr] sa fie inclus in [wantedLeft, wantedRight]
    //caz in care nu mai are rost sa merg mai departe, ma opresc si trimit toata solutia
    if (wantedLeft <= st && dr <= wantedRight)
        return arb[nod];
    //Daca am intervale care se intersecteaza cu wantedLeft, wantedRight, o parte din solutia optima ar putea fi acolo
    int med = (st + dr) / 2;
    if (wantedLeft <= med)
    {
        now = arbQuery(st, med, 2 * nod, wantedLeft, wantedRight);
        if (now.val == ans.val)
        {
            ans.num += now.val;
            ans.num = ans.num % MOD;
        }
        if (now.val > ans.val)
            ans.num = now.num, ans.val = now.val;
    }
    if (med < wantedRight)
    {
        now = arbQuery(med + 1, dr, 2 * nod + 1, wantedLeft, wantedRight);
        if (now.val == ans.val)
        {
            ans.num += now.val;
            ans.num = ans.num % MOD;
        }
        if (now.val > ans.val)
            ans = now;
    }
     
    return ans;
}
 
void arbUpdate(int st, int dr, int nod, int wantedNod, query info)
{
    if (st == dr) //Am ajuns la nodul cautat din arbore
    {
        arb[nod] = info;
        return ;
    }
    int med = (st + dr) / 2;
     
    int choice;
    if (wantedNod <= med)
    {
        arbUpdate(st, med, 2 * nod, wantedNod, info);
        choice = 2 * nod;
    }
    else
    {
        arbUpdate(med + 1, dr, 2 * nod + 1, wantedNod, info);
        choice = 2 * nod + 1;
    }
     
    if (info.val == arb[nod].val)
    {
        arb[nod].num += info.num;
        arb[nod].num %= MOD;
    }
    if (info.val > arb[nod].val)
        arb[nod] = info;
}
 
int main()
{
    int i, N;
     
    freopen("subsiruri.in", "r", stdin);
    freopen("subsiruri.out", "w", stdout);
     
    //Citesc vectorul
    scanf("%d", &N);
    for (i = 1; i <= N; i ++)
        scanf("%d", &x[i]);
     
    //Brute force O(N ^ 2)
    int dp[NMAX], how[NMAX], j;
     
    memset(dp, 0, sizeof(dp));
    memset(how, 0, sizeof(how));
     
    int bestChoice, numChoices;
     
    for (i = 1; i <= N; i ++)
    {
        bestChoice = numChoices = 0;
        for (j = 1; j < i; j ++)
            if (dp[j] > bestChoice && x[j] < x[i])
                bestChoice = dp[j];
        dp[i] = bestChoice + 1;
        for (j = 1; j < i; j ++)
            if (dp[j] == bestChoice && x[j] < x[i])
            {
                numChoices += how[j];
                numChoices = numChoices % 9901;
            }
        if (numChoices == 0)
            numChoices ++;
        how[i] = numChoices;
    }
     
    bestChoice = 0; numChoices = 0;
    for (i = 1; i <= N; i ++)
    {
        if (dp[i] == bestChoice)
            numChoices += how[i];
        if (dp[i] > bestChoice)
            bestChoice = dp[i], numChoices = how[i];
    }
     
    printf("%d\n%d", bestChoice, numChoices);
    return 0;
     
    //Normalizez datele
    for (i = 1; i <= N; i ++)
        sortedX[i] = x[i];
    sort(sortedX + 1, sortedX + N + 1);
     
    int st, dr, med;
    for (i = 1; i <= N; i ++)
    {
        st = 1; dr = N; 
        while (st <= dr)
        {
            med = (st + dr) / 2;
            if (sortedX[med] == x[i])
            {
                x[i] = med;
                break;
            }
            if (sortedX[med] < x[i])
                st = med + 1;
            else
                dr = med - 1;
        }
    }
     
    query now;
     
    for (i = 1; i <= N; i ++)
    {
        //Un QUERY pe intervalul [i, j] imi da lungimea unei subsir crescator maximal si cate exista
        //astfel incat ultimul element din subsir sa se afle in intervalul [i, j]
         
        //La pasul curent un subsir crescator maximal care se termina in x[i] poate fi obtinut din 
        //orice alt subsir crescator maximal care se termina undeva in intervalul [1, x[i] - 1]
        now = arbQuery(1, N, 1, 1, x[i] - 1);
        now.val ++;
        if (now.num == 0)
            now.num = 1;
        //Lungimea subsirului crescator maximal va creste cu 1 (am adaugat elementul x[i]), iar numarul va
        //ramane acelasi (cel dat de queryul dinainte, deoarece se adauga un singur element la ce era inainte)
        arbUpdate(1, N, 1, x[i], now);
    }
     
    //Afisez solutia finala
    now = arbQuery(1, N, 1, 1, N);
    printf("%d\n%d", now.val, now.num);
    return 0;
}