Cod sursa(job #2348911)

Utilizator CronosClausCarare Claudiu CronosClaus Data 20 februarie 2019 08:28:08
Problema Radiatie Scor 0
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 4.3 kb
#include <bits/stdc++.h>
#define ll int
#define pp pair< int, int >
#define tt tuple< int, int, int >

using namespace std;

const int mxn = 15 * 1000 + 10;
const int mxx = 2e9;

vector< pp > graf[ mxn ];
vector< int > partial[ mxn ];
ll dist[ mxn ];

int nivel[ 2 * mxn ];
int parcurgere[ mxn ];
int poz[ mxn ];
int p;

int arb_min[ 8 * mxn ], arb_max[ 8 * mxn ];

int n, m, k;

int a, b;

inline tt atribuire(pp muchie, int daddy){
    return make_tuple(muchie.first, muchie.second, daddy);
}

void construire_partial(){
    priority_queue< tt, vector< tt >, greater< tt > > q_min;
    bitset< mxn > viz;
    int ramas = n - 1;
    for(auto it: graf[ 1 ])
        q_min.push( atribuire( it, 1 ) );
    viz[ 1 ] = 1;
    int cost, nod, daddy;
    while(!q_min.empty() && ramas > 0){
        tie(cost, nod, daddy) = q_min.top();
        q_min.pop();
        if(viz[ nod ] == 0){
            partial[ daddy ].push_back( nod );
            ramas--;
            viz[ nod ] = 1;
            dist[ nod ] = cost;
            for(auto it: graf[ nod ])
                q_min.push( atribuire( it, nod ) );
        }
    }
}

void euler(int nod, int lvl){
    nivel[ nod ] = lvl;
    poz[ nod ] = p;
    parcurgere[ p++ ] = nod;
    for(auto it: partial[ nod ]){
        euler( it, lvl + 1 );
        parcurgere[ p++ ] = nod;
    }
}

int build_lca(int nod, int st, int sf){
    if(st == sf){
        arb_min[ nod ] = parcurgere[ st ];
        return nivel[ arb_min[ nod ] ];
    }
    else{
        int mid = (st + sf) / 2;
        int n1 = build_lca(2 * nod, st, mid);
        int n2 = build_lca(2 * nod + 1, mid + 1, sf);
        if(n1 <= n2){
            arb_min[ nod ] = arb_min[ 2 * nod ];
            return n1;
        }
        else{
            arb_min[ nod ] = arb_min[ 2 * nod + 1];
            return n2;
        }
    }
}

int lca(int nod, int st, int sf){
    if(st >= a && sf <= b)
        return arb_min[ nod ];
    else{
        if(st <= b && sf >= a){
            int mid = (st + sf) / 2;
            int n1 = lca(2 * nod, st, mid);
            int n2 = lca(2 * nod + 1, mid + 1, sf);
            if(nivel[ n1 ] <= nivel[ n2 ]){
                return n1;
            }
            else{
                return n2;
            }
        }
    }
    return mxn;
}

void atribuire_interval(int x, int y){
    a = poz[ x ];
    b = poz[ y ];
    if(a > b)
        swap(a, b);
}

int build_radiation(int nod, int st, int sf){
    if(st == sf){
        arb_max[ nod ] = parcurgere[ st ];
        return dist[ arb_max[ nod ] ];
    }
    else{
        int mid = (st + sf) / 2;
        int n1 = build_radiation(2 * nod, st, mid);
        int n2 = build_radiation(2 * nod + 1, mid + 1, sf);
        if(n1 >= n2){
            arb_max[ nod ] = arb_max[ 2 * nod ];
            return n1;
        }
        else{
            arb_max[ nod ] = arb_max[ 2 * nod + 1];
            return n2;
        }
    }
}

int query(int nod, int st, int sf){
    if(st >= a && sf <= b)
        return arb_max[ nod ];
    else{
        if(st <= b && sf >= a){
            int mid = (st + sf) / 2;
            int n1 = query(2 * nod, st, mid);
            int n2 = query(2 * nod + 1, mid + 1, sf);
            if(dist[ n1 ] >= dist[ n2 ]){
                return n1;
            }
            else{
                return n2;
            }
        }
    }
    return 0;
}

int main()
{
    ifstream cin("radiatie.in");
    ofstream cout("radiatie.out");
    cin>> n >> m >> k;
    for(int i = 1, x, y, z; i <= m; i++){
        cin>> x >> y >> z;
        graf[ x ].push_back(make_pair(z, y));
        graf[ y ].push_back(make_pair(z, x));
    }
    construire_partial();
    euler(1, 1);
    build_lca(1, 0, p - 1);
    build_radiation(1, 0 ,p - 1);
    nivel[ mxn ] = mxn;
    int aux, daddy;
    int q1, q2;
    for(int i = 1, x, y; i <= k; i++){
        cin>> x >> y;
        atribuire_interval(x, y);
        daddy = lca(1, 0, p - 1);
        aux = dist[ daddy ];
        dist[ daddy ] = 0;

        atribuire_interval(daddy, x);
        q1 = query(1, 0, p - 1);

        atribuire_interval(daddy, y);
        q2 = query(1, 0, p - 1);
        dist[ daddy ] = aux;

        cout<< max(dist[ q1 ], dist[ q2 ]) << '\n';
    }
    return 0;
}