Cod sursa(job #220957)

Utilizator CezarMocanCezar Mocan CezarMocan Data 13 noiembrie 2008 21:09:43
Problema Atac Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.54 kb
#include <cstdio>
#include <algorithm>
#include <vector>
#define INF 1000000000;
#define MAX_N 64100;

using namespace std;

int n, m, p, i, j, a, b, c, d, x, y, lc, min1, min2, z, xnou, ynou;

int viz[MAX_N], e[MAX_N], niv[MAX_N], rmq[MAX_N][30];
int dnk[MAX_N][30], mn[MAX_N][30], par[MAX_N], csp[MAX_N], p2[30], level[MAX_N];
int pp1[MAX_N], pp2[MAX_N], pp[MAX_N];

vector <int> v[MAX_N], cs[MAX_N];

inline int min(int a, int b) {
    if (a < b)
        return a;
    else
        return b;    
}

inline int max(int a, int b) {
    if (a > b)
        return a;
    else
        return b;    
}

void euler(int nod, int lvl) {
    int i;
    e[0]++;
    e[e[0]] = nod;
    niv[e[0]] = lvl;
    level[nod] = lvl;
    
    for (i = 0; i < v[nod].size(); ++i) 
        if (viz[v[nod][i]] == 0)  {
            viz[v[nod][i]] = 1;            
            par[v[nod][i]] = nod;
            csp[v[nod][i]] = cs[nod][i];
            euler(v[nod][i], lvl + 1);
            e[0]++;
            e[e[0]] = nod;    
            niv[e[0]] = lvl;
        }
}

int lca(int a, int b) {
    int x, y, z, mn;
    x = min(pp1[a], pp1[b]);
    y = max(pp2[a], pp2[b]);
    
    z = y - x + 1;
    
    if (niv[rmq[x][pp[z]]] < niv[rmq[y-p2[pp[z]]+1][pp[z]]] ) 
        mn = rmq[x][pp[z]];        
    else
        mn = rmq[y-p2[pp[z]]+1][pp[z]];
        
    return e[mn];
}

int det_min(int p, int q) {
    int minim, t, pp, qq;
    minim = INF;
    qq = p;
    pp = level[p] - level[q];   
    while (pp && qq) {
        t = 0;
        while (1 << (t + 1) < pp)         
            ++t;
        if (mn[qq][t] < minim)
            minim = mn[qq][t];
        qq = dnk[qq][t];
        pp -= (1 << t); 
    }
    return minim;
}

int main(){
    freopen("atac.in", "r", stdin);
    freopen("atac.out", "w", stdout);
    
    scanf("%d%d%d", &n, &m, &p);
    
    for (i = 1; i < n; i++) {
        scanf("%d%d", &a, &b);
        
        v[i + 1].push_back(a);
        cs[i + 1].push_back(b);
        
        v[a].push_back(i + 1);
        cs[a].push_back(b);    
    }
    
    viz[1] = 1;
    euler(1, 1);
    
    for (i = 1; i <= n; i++) {
        dnk[i][0] = par[i];
        mn[i][0] = csp[i];
    }
    
    for (i = 1; i <= n; i++)
        for (j = 1; (1 << j) <= n; j++) {
            dnk[i][j] = dnk[dnk[i][j-1]][j-1];
            mn[i][j] = min(mn[dnk[i][j-1]][j-1], mn[i][j-1]);    
        }
        
    //  initializari pentru LCA  
    for (i = 1; i <= e[0]; i++) {
        if (pp1[e[i]] == 0)        
            pp1[e[i]] = i;
        pp2[e[i]] = i;
    }
            
    for (i = 0; i <= 20; i++)
        p2[i] = 1 << i;      
        
    pp[1] = 0;
    for (i = 2; i <= 64000; i++) 
        pp[i] = pp[i / 2] + 1;
          
        
    for (i = 1; i <= e[0]; i++)
        rmq[i][0] = i;
        
    for (j = 1; p2[j] <= e[0]; j++) 
        for (i = 1; i <= e[0]; i++) {
            rmq[i][j] = rmq[i][j-1];
            if (niv[rmq[i][j]] > niv[rmq[i + p2[j-1]][j-1]]) 
                rmq[i][j] = rmq[i + p2[j-1]][j-1];   
        }
            
        
    scanf("%d%d%d%d%d%d", &x, &y, &a, &b, &c, &d);
    for (i = 1; i <= m; i++) {
        lc = lca(x, y);        
        min1 = det_min(x, lc);
        min2 = det_min(y, lc);
        z = min(min1, min2);
        if (i >= p)
            printf("%d\n", z);
        xnou = (x * a + y * b) % n + 1; 
        ynou = (y * c + z * d) % n + 1;
        
        x = xnou;
        y = ynou;
    }
    
    return 0;
}