Cod sursa(job #1550538)

Utilizator bciobanuBogdan Ciobanu bciobanu Data 13 decembrie 2015 21:09:29
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.27 kb
#include <bits/stdc++.h>

using namespace std;

const int MAX_N = 100000;
const int NIL = -1;
const int BUFFSIZE = 65536;

inline char getChar()
{
    static char buff[BUFFSIZE];
    static int pos = BUFFSIZE;

    if (pos == BUFFSIZE)
    {
        fread_unlocked(buff, 1, BUFFSIZE, stdin);
        pos = 0;
    }
    return buff[pos++];
}

inline int readInt()
{
    register int q = 0;
    char c;

    do
    {
        c = getChar();
    } while (!isdigit(c));
    do
    {
        q = (q << 1) + (q << 3) + (c - '0');
        c = getChar();
    } while (isdigit(c));
    return q;
}

struct Edge
{
    int v;
    int next;
};

Edge l[2 * MAX_N - 2];
int head[MAX_N];
int key[MAX_N];

// HPD
int parent[MAX_N];
int heavy[MAX_N];
int depth[MAX_N];
int root[MAX_N];
int treePos[MAX_N];
int T[2 * MAX_N];

int N;

void addEdge(int u, int v, int pos)
{
    l[pos].v = v;
    l[pos].next = head[u];
    head[u] = pos;
}

int DFS(int u)
{
    int currSize = 1, maxSubTree = 0;
    for (int i = head[u]; i != NIL; i = l[i].next)
    {
        int v = l[i].v;
        if (parent[u] != v)
        {
            parent[v] = u;
            depth[v] = depth[u] + 1;
            int subTree = DFS(v);
            if (subTree > maxSubTree)
            {
                heavy[u] = v;
                maxSubTree = subTree;
            }
            currSize += subTree;
        }
    }
    return currSize;
}

void buildHPD(int N)
{
    int ptr = 0;

    depth[0] = 0;
    DFS(0);

    for (int i = 0; i < N; i++)
    {
        if (heavy[parent[i]] != i)
        {
            for (int j = i; j != NIL; j = heavy[j])
            {
                root[j] = i;
                T[N + ptr] = key[j];
                treePos[j] = ptr++;
            }
        }
    }

    for (int i = N - 1; i > 0; i--)
        T[i] = max(T[2 * i], T[2 * i + 1]);

}

int segQuery(int u, int v) // [u, v]
{
    int q = 0;

    u += N;
    v += N + 1;

    while (u < v)
    {
        if (u & 1)
            q = max(q, T[u++]);
        if (v & 1)
            q = max(q, T[--v]);
        u >>= 1;
        v >>= 1;
    }
    return q;
}

void segUpdate(int u, int newKey)
{
    int q;

    u += N;

    T[u] = newKey;

    while (u > 1)
    {
        q = u / 2;
        T[q] = max(T[u], T[u ^ 1]);
        u = q;
    }
}

int queryPath(int u, int v)
{
    int q = 0;

    while (root[u] != root[v])
    {
        if (depth[root[u]] > depth[root[v]])
            swap(u, v);

        q = max(q, segQuery(treePos[root[v]], treePos[v]));
        v = parent[root[v]];
    }

    if (depth[u] > depth[v])
        swap(u, v);

    q = max(q, segQuery(treePos[u], treePos[v]));
    return q;
}

int main()
{
    freopen("heavypath.in", "r", stdin);
    freopen("heavypath.out", "w", stdout);
    int M;
    int u, v;
    N = readInt(); M = readInt();

    for (int i = 0; i < N; i++)
    {
        head[i] = NIL;
        heavy[i] = NIL;
        key[i] = readInt();
    }

    for (int i = 0; i < N - 1; i++)
    {
        u = readInt() - 1; v = readInt() - 1;
        addEdge(u, v, 2 * i);
        addEdge(v, u, 2 * i + 1);
    }

    buildHPD(N);

    while (M--)
    {
        int opType = readInt();
        u = readInt(); v = readInt();

        if (opType)
            printf("%d\n", queryPath(u - 1, v - 1));
        else
            segUpdate(treePos[u - 1], v);
    }
    return 0;
}