Cod sursa(job #1877099)

Utilizator ajeccAjechiloae Eugen ajecc Data 12 februarie 2017 22:23:36
Problema Heavy Path Decomposition Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 7.54 kb
#include <bits/stdc++.h>
#define for0(i,n) for(int i=0; i<n; i++)
#define for1(i,n) for(int i=1; i<=n; i++)
#define pb push_back
#define mp make_pair
#define all(v) v.begin(), v.end()
#define V vector<int>
#define VP vector<pair<int, int> >
#define clr(A,x) memset(A, x, sizeof(A))
#define cpy(A,B) memcpy(A, B, sizeof(B))
#define g(stream, s) getline(stream, s)
#define FASTIO ios_base::sync_with_stdio(0)
typedef long long ll;
typedef unsigned long long ull;
using namespace std;

const int CHARMAX = (1 << 10);
const int INFINT = 2000000000 + 777;
const ll INFLL = (1LL << 62);

/*class InParsare
{
private:
    FILE *fin;
    char *buffer;
    size_t index_of_buffer;

    char read_character()
    {
        index_of_buffer++;
        if(index_of_buffer == CHARMAX)
        {
            fread(buffer, 1, CHARMAX, fin);
            index_of_buffer = 0;
        }
        return buffer[index_of_buffer];
    }

public:
    InParsare(const char *name)
    {
        fin = fopen(name, "r");
        buffer = new char[CHARMAX]();
        index_of_buffer = CHARMAX - 1;
    }

    template<class T>
    InParsare &operator >> (T &n)
    {
        char c;
        while(!isdigit(c = read_character()) && c != '-');

        int sgn = 1;
        if(c == '-')
        {
            n = 0;
            sgn = -1;
        }
        else n = c - '0';

        while(isdigit(c = read_character()))
            n = n * 10 + c - '0';
        n *= sgn;

        return *this;
    }
};

class OutParsare
{
private:
    FILE *fout;
    char *buffer;
    size_t index_of_buffer;

    void write_character(char character)
    {
        if(index_of_buffer == CHARMAX)
        {
            fwrite(buffer, 1, CHARMAX, fout);
            index_of_buffer = 0;
            buffer[index_of_buffer++] = character;
        }
        else buffer[index_of_buffer++] = character;
    }

public:

    OutParsare(const char *name)
    {
        fout = fopen(name, "w");
        buffer = new char[CHARMAX]();
        index_of_buffer = 0;
    }

    ~OutParsare()
    {
        fwrite(buffer, 1, index_of_buffer, fout);
        fclose(fout);
    }
    template<class T>
    OutParsare &operator << (T n)
    {
        if(typeid(T).name() == typeid(char).name())
        {
            write_character(n);
            return *this;
        }

        if(n <= 9)
            write_character(n + '0');
        else
        {
            (*this) << (n / 10);
            write_character(n % 10 + '0');
        }

        return *this;
    }

};*/

//InParsare fin("statiuni.in"); /// merg numai pt numere
//OutParsare fout("statiuni.out"); /// merg numai pt numere + caractere individuale, nu stringuri
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");

const int NMAX = 1e5 + 1;
const int MOD = 1e9 + 7;
#define LN 14

int n, q;
V arbore[NMAX], chains[NMAX];
int val[NMAX], sz[NMAX], ind_chain[NMAX], chain_head[NMAX], pa[LN][NMAX], depth[NMAX], no_chains = 1;
int **aint;

struct mlc
{
    int x, y;
    mlc()
    {
        x = y = 0;
    }
    mlc(int _x, int _y)
    {
        x = _x;
        y = _y;
    }
};
mlc coresp[NMAX];

void get_sz(int nod = 0, int p = -1, int d = 0)
{
    sz[nod] += 1;
    pa[0][nod] = p;
    depth[nod] = d;

    for(auto i: arbore[nod])
        if(i != p)
        {
            get_sz(i, nod, d + 1);
            sz[nod] += sz[i];
        }
}

void hld(int nod = 0, int p = -1)
{
    if(!chain_head[no_chains]) chain_head[no_chains] = nod;
    chains[no_chains].pb(nod);
    ind_chain[nod] = no_chains;

    int next = -1, sz_max = -1;
    for(auto i: arbore[nod])
        if(i != p && sz_max < sz[i])
        {
            sz_max = sz[i];
            next = i;
        }

    if(next != -1) hld(next, nod);

    for(auto i: arbore[nod])
        if(i != p && i != next)
        {
            no_chains++;
            hld(i, nod);
        }
}

void construct_aint()
{
    aint = new int* [no_chains + 1];
    for1(i, no_chains)
        aint[i] = new int [4 * (chains[i].size() + 1)];

    for1(i, no_chains)
        for0(j, chains[i].size())
            coresp[chains[i][j]] = mlc(i, j + 1);
}

void update(int x, int pos, int vval, int cur, int l, int r)
{
    if(l == r)
    {
        aint[x][cur] = vval;
        return;
    }

    int mid = (l + r) / 2;
    if(pos <= mid) update(x, pos, vval, 2 * cur, l, mid);
    else update(x, pos, vval, 2 * cur + 1, mid + 1, r);

    aint[x][cur] = max(aint[x][2 * cur], aint[x][2 * cur + 1]);
}

int ret = -1;
void query(int x, int start, int finish, int cur, int l, int r)
{
    if(l >= start && r <= finish)
    {
        ret = max(ret, aint[x][cur]);
        return;
    }

    int mid = (l + r) / 2;

    if(start <= mid) query(x, start, finish, 2 * cur, l, mid);
    if(mid < finish) query(x, start, finish, 2 * cur + 1, mid + 1, r);
}

int query_up(int u, int v)
{
    int uchain = ind_chain[u], vchain = ind_chain[v], ans = -1;
    //cout << u << ' ' << pa[0][chain_head[uchain]];

    for(;;)
    {
        if(uchain == vchain)
        {
            ret = -1;
            if(coresp[u].y > coresp[v].y)
                    swap(u, v);
            query(coresp[u].x, coresp[u].y, coresp[v].y, 1, 1, chains[ind_chain[u]].size());
            if(ret > ans) ans = ret;
            return ans;
        }

        ret = -1;
      //  cout << u << ' ' << chain_head[ind_chain[u]] << endl;
        query(coresp[u].x, min(coresp[u].y, coresp[chain_head[ind_chain[u]]].y), max(coresp[u].y, coresp[chain_head[ind_chain[u]]].y), 1, 1, chains[ind_chain[u]].size());
        if(ret > ans) ans = ret;
        u = pa[0][chain_head[ind_chain[u]]];
        uchain = ind_chain[u];
    }
    return 0;
}

int lca(int u, int v)
{
    if(depth[u] < depth[v])
        swap(u, v);

    int diff = depth[u] - depth[v];
    for(int i = 0; i < LN; i++)
        if((diff >> i) & 1)
            u = pa[i][u];

    if(u == v) return u;
    for(int i = LN - 1; i >= 0; i--)
        if(pa[i][u] != pa[i][v])
        {
            u = pa[i][u];
            v = pa[i][v];
        }
    return pa[0][u];
}



int main()
{
    fin >> n >> q;
    for0(i, n)
    {
        fin >> val[i];
        for0(j, LN)
            pa[j][i] = -1;
    }

    for1(i, n - 1)
    {
        int a, b;
        fin >> a >> b;
        a--; b--;
        arbore[a].pb(b);
        arbore[b].pb(a);
    }

    get_sz();
    hld();
    construct_aint();

    for0(i, n)
        update(coresp[i].x, coresp[i].y, val[i], 1, 1, chains[ind_chain[i]].size());

    for(int i = 1; i < LN; i++)
        for(int j = 0; j < n; j++)
            if(pa[i - 1][j] != -1)
                pa[i][j] = pa[i - 1][pa[i - 1][j]];

    while(q--)
    {
        int t, a, b;
        fin >> t >> a >> b;
        a--; b--;
        if(!t)
            update(coresp[a].x, coresp[a].y, b, 1, 1, chains[ind_chain[a]].size());
        else
        {
            ret = -1;
            if(ind_chain[a] == ind_chain[b])
            {
                if(coresp[a].y > coresp[b].y)
                    swap(a, b);
                query(coresp[a].x, coresp[a].y, coresp[b].y, 1, 1, chains[ind_chain[a]].size());
                fout << ret << '\n';
                continue;
            }
            int LCA = lca(a, b);
            fout << max(query_up(b, LCA), query_up(a, LCA)) << '\n';

        }
    }

    return 0;
}
/*
11 7
1 2 3 4 5 6 7 8 9 10 11
1 2
2 3
2 7
3 4
3 5
3 6
7 8
8 9
4 10
4 11
*/