Cod sursa(job #1966721)

Utilizator TimitocArdelean Andrei Timotei Timitoc Data 15 aprilie 2017 15:24:13
Problema Heavy Path Decomposition Scor 40
Compilator cpp Status done
Runda Arhiva educationala Marime 3.65 kb
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#define MAXN 100050

using namespace std;

int n, m;
int v[MAXN];
vector<int> graf[MAXN];
int parent[MAXN], lparent[MAXN], depth[MAXN];
int nq;
int lweight[MAXN], core[MAXN], rel[MAXN];
vector<int> lanturi[MAXN];

struct SegmentTree
{
    int *a;
    int sz;
    SegmentTree(int ind)
    {
        sz = lanturi[ind].size()-1;
        a = new int[sz*4];
        init(1, sz, 1, ind);
    }

    void init(int st, int dr, int nod, int ind)
    {
        if (st == dr) {
            a[nod] = v[lanturi[ind][st]];
            return;
        }
        int mid = (st+dr)>>1;
        init(st, mid, nod<<1, ind);
        init(mid+1, dr, nod<<1 | 1, ind);
        a[nod] = max(a[nod<<1], a[nod<<1 | 1]);
    }

    void update(int pos, int val)
    {
        update(pos, val, 1, sz, 1);
    }

    int getMax(int qst, int qdr)
    {
        return getMax(qst, qdr, 1, sz, 1);
    }

    void update(int pos, int val, int st, int dr, int nod)
    {
        if (st == dr) {
            a[nod] = val;
            return;
        }
        int mid = (st + dr) >> 1;
        if (pos <= mid)
            update(pos, val, st, mid, nod<<1);
        else
            update(pos, val, mid+1, dr, nod << 1 | 1);
        a[nod] = max(a[nod<<1], a[nod<<1 | 1]);
    }

    int getMax(int qst, int qdr, int st, int dr, int nod)
    {
        if (qst <= st && dr <= qdr)
            return a[nod];
        int mid = (st + dr) >> 1;
        int maxi = -1;
        if (qst <= mid)
            maxi = max(maxi, getMax(qst, qdr, st, mid, nod<<1));
        if (qdr > mid)
            maxi = max(maxi, getMax(qst, qdr, mid+1, dr, nod<<1 | 1));
        return maxi;
    }

}*aint[MAXN];


void read()
{
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; i++)
        scanf("%d", &v[i]);
    int x, y;
    for (int i = 1; i <= n-1; i++) {
        scanf("%d %d", &x, &y);
        graf[x].push_back(y);
        graf[y].push_back(x);
    }
}

void build(int nod, int d)
{
    depth[nod] = d;
    int maxi = -1, pos;
    for (int y : graf[nod]) {
        if (depth[y]) continue;
        parent[y] = nod;
        build(y, d+1);
        if (lweight[core[y]] > maxi) {
            maxi = lweight[core[y]];
            pos = core[y];
        }
    }
    if (maxi == -1)
        core[nod] = ++nq;
    else
        core[nod] = pos;
    lanturi[core[nod]].push_back(nod);
    lweight[core[nod]]++;
    for (int y : graf[nod])
        if (parent[y] == nod && core[y] != core[nod])
            lparent[core[y]] = nod;
}

void diapazon()
{
    for (int i = 1; i <= nq; i++) {
        lanturi[i].push_back(-1);
        std::reverse(lanturi[i].begin(), lanturi[i].end());
        for (int j = 1, t = lanturi[i].size(); j < t; j++)
            rel[lanturi[i][j]] = j;
        aint[i] = new SegmentTree(i);
    }
}

void update(int x, int y)
{
    aint[core[x]]->update(rel[x], y);
}

int query(int x, int y)
{
    if (core[x] == core[y])
        return aint[core[x]]->getMax(min(rel[x], rel[y]), max(rel[x], rel[y]));
    if (depth[lanturi[core[x]][1]] > depth[lanturi[core[y]][1]])
        swap(x, y);
    return max(aint[core[y]]->getMax(1, rel[y]), query(x, lparent[core[y]]));
}

int main()
{
    freopen("heavypath.in", "r", stdin);
    freopen("heavypath.out", "w", stdout);

    read();
    build(1, 1);
    diapazon();
    for (int i = 1; i <= m; i++) {
        int t, x, y;
        scanf("%d %d %d", &t, &x, &y);
        if (t == 0)
            update(x, y);
        else
            printf("%d\n", query(x, y));
    }

    return 0;
}