Cod sursa(job #1875856)

Utilizator ajeccAjechiloae Eugen ajecc Data 11 februarie 2017 18:00:21
Problema Heavy Path Decomposition Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 6.41 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 = 153 + 1;
const int MOD = 1e9 + 7;

int n, q;
V arbore[NMAX], chains[NMAX];
int val[NMAX], sz[NMAX], ind_chain[NMAX], chain_head[NMAX], tata[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 = 1, int p = 1)
{
    tata[nod] = p;
    sz[nod] += 1;

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

void hld(int nod = 1, int p = 0)
{
    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 main()
{
    fin >> n >> q;
    for1(i, n)
        fin >> val[i];
    for1(i, n - 1)
    {
        int a, b;
        fin >> a >> b;
        arbore[a].pb(b);
        arbore[b].pb(a);
    }

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

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

    while(q--)
    {
        int t, a, b;
        fin >> t >> 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;
            }

            if(ind_chain[tata[chain_head[ind_chain[a]]]] != ind_chain[b])
                swap(a, b);

            int temp;
            int parent = tata[chain_head[ind_chain[a]]], cap = chain_head[ind_chain[a]];
            if(coresp[b].y > coresp[parent].y)
                swap(b, parent);
            query(coresp[b].x, coresp[b].y, coresp[parent].y, 1, 1, chains[ind_chain[b]].size());

            temp = ret;
            ret = -1;

            if(coresp[a].y > coresp[cap].y)
                swap(a, cap);
            query(coresp[a].x, coresp[a].y, coresp[cap].y, 1, 1, chains[ind_chain[a]].size());
            fout << max(temp, ret) << '\n';
        }
    }

    return 0;
}