Cod sursa(job #809694)

Utilizator repp4raduRadu-Andrei Szasz repp4radu Data 8 noiembrie 2012 20:45:08
Problema Atac Scor 40
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.87 kb
#include <fstream>
#include <vector>

#define MAX 32005
#define LMAX 16
#define INF 0x3f3f3f3f
#define pb push_back
#define mp make_pair
#define f first
#define s second
#define PII pair<int, int>

using namespace std;

vector< PII > v[MAX]; vector< int > euler;
int n, m, p, x, y, X, Y, A, B, C, D, NX, NY, rez;
int dad[LMAX][MAX], minim[LMAX][MAX], lvl[MAX], rmq[LMAX][MAX], log[MAX << 1], first[MAX];

void citire()
{
    ifstream in("atac.in");
    in>>n>>m>>p;
    for(int i = 2; i <= n; i++)
    {
        in>>x>>y;
        v[i].pb(mp(x, y));
        v[x].pb(mp(i, y));
    }
    in>>X>>Y>>A>>B>>C>>D; in.close(); euler.pb(0);
    for(int i = 2; i <= 2 * n; i++) log[i] = log[i >> 1] + 1;
}

void dfs(int nod, int tata, int nivel, int cost)
{
    lvl[nod] = nivel; dad[0][nod] = tata; minim[0][nod] = cost; first[nod] = euler.size();
    euler.pb(nod);
    for(vector< PII > :: iterator it = v[nod].begin(); it != v[nod].end(); it++)
    {
        int dest = (*it).f, c = (*it).s;
        if(dest == tata) continue;
        dfs(dest, nod, nivel + 1, c);
        euler.pb(nod);
    }
}

void buildAncestors()
{
    minim[0][1] = INF;
    for(int i = 1; i <= log[n]; i++)
        for(int nod = 1; nod <= n; nod++)
        {
            int tata = dad[i - 1][nod];
            minim[i][nod] = min(minim[i - 1][nod], minim[i - 1][tata]);
            dad[i][nod] = dad[i - 1][tata];
        }
}

void buildRMQ()
{
    for(int i = 1; i < euler.size(); i++) rmq[0][i] = euler[i];
    for(int i = 1; i <= log[euler.size()]; i++)
        for(int nod = 1; nod < euler.size() - (1 << i); nod++)
        {
            rmq[i][nod] = rmq[i - 1][nod];
            if(lvl[rmq[i][nod]] > lvl[rmq[i - 1][nod + (1 << (i - 1))]]) rmq[i][nod] = rmq[i - 1][nod + (1 << (i - 1))];
        }
}

int getLCA(int x, int y)
{
    if(first[x] > first[y]) swap(x, y);
    if(x == y) return x;
    int dif = first[y] - first[x] + 1, lg = log[dif];
    if(lvl[rmq[lg][first[x]]] < lvl[rmq[lg][first[y] - (1 << lg) + 1]]) return rmq[lg][first[x]];
    return rmq[lg][first[y] - (1 << lg) + 1];
}

int query(int x, int y)
{
    if(x == y) return INF;
    int dif = lvl[x] - lvl[y], sol = INF;
    for(int i = 0; i < LMAX; i++)
        if(dif & (1 << i))
        {
            sol = min(sol, minim[i][x]);
            x = dad[i][x];
        }
    return sol;
}

void solve()
{
    ofstream out("atac.out");
    while(m--)
    {
        int ans = 0;
        if(X != Y)
        {
           int lca = getLCA(X, Y);
           ans = min(query(X, lca), query(Y, lca));
        }
        if(m < p) out<<ans<<"\n";
        NX = (X * A + Y * B) % n + 1;
        NY = (Y * C + ans * D) % n + 1;
        X = NX; Y = NY;
    }
    out.close();
}

int main()
{
    citire();
    dfs(1, 0, 1, 0);
    buildRMQ();
    buildAncestors();
    solve();
    return 0;
}