Cod sursa(job #1660341)

Utilizator bogdan10bosBogdan Sitaru bogdan10bos Data 22 martie 2016 23:35:18
Problema Heavy Path Decomposition Scor 40
Compilator cpp Status done
Runda Arhiva educationala Marime 5.14 kb
#include <bits/stdc++.h>

using namespace std;

#define FILE_IO

const int buffer = 1 << 13;
int cnt = buffer - 1;
char buff[buffer + 5];

char gchar()
{
    if(++cnt == buffer)
    {
        cnt = 0;
        fread(buff, buffer, 1, stdin);
    }
    return buff[cnt];
}

int gint()
{
    char ch = gchar();
    while(ch < '0' || '9' < ch)
        ch = gchar();
    int x = 0;
    while('0' <= ch && ch <= '9')
    {
        x = x * 10 + ch - '0';
        ch = gchar();
    }
    return x;
}

int N, M;
int hvy[100005], val[100005];
int h[100005], poseul[100005];
int E, rmq[200005][20], p2[200005];
int L, lant[100005], fth[100005], pos[100005];

vector <int> edg[100005];
vector <int> lnt[100005];

void DFS(int nod, int _fth)
{
    fth[nod] = _fth;
    h[nod] = h[_fth] + 1;
    E++;
    poseul[nod] = E;
    rmq[E][0] = nod;
    hvy[nod] = 1;

    int nodmax = 0;
    for(vector <int> :: iterator it = edg[nod].begin(); it != edg[nod].end(); it++)
    {
        int nxt = *it;
        if(nxt == _fth)  continue;

        DFS(nxt, nod);
        rmq[++E][0] = nod;

        hvy[nod] += hvy[nxt];
        if(hvy[nxt] > hvy[nodmax])  nodmax = nxt;
    }

    if(nodmax == 0)
    {
        lnt[++L].push_back(nod);
        lant[nod] = L;
    }
    else
    {
        lant[nod] = lant[nodmax];
        lnt[ lant[nod] ].push_back(nod);
    }
}

int minh(int a, int b)
{
    if(h[a] < h[b]) return a;
    return b;
}

bool cmph(int a, int b)
{
    return h[a] > h[b];
}

int LCA(int a, int b)
{
    int st = poseul[a];
    int dr = poseul[b];
    if(st > dr) swap(st, dr);
    int pw = p2[dr - st + 1];
    return minh(rmq[st][pw], rmq[dr - (1 << pw) + 1][pw]);
}

class segmentTree
{
private:
    int *aint;
    int N, ans, ind;

    void B(int nod, int st, int dr)
    {
        if(st == dr)
        {
            aint[nod] = val[ lnt[ind][st - 1] ];
            return;
        }

        int mij = st + (dr - st) / 2;
        B(nod * 2, st, mij);
        B(nod * 2 + 1, mij + 1, dr);
        aint[nod] = max(aint[nod * 2], aint[nod * 2 + 1]);
    }

    void U(int nod, int st, int dr, int pos, int val)
    {
        if(st == dr)
        {
            aint[nod] = val;
            return;
        }
        int mij = st + (dr - st) / 2;
        if(pos <= mij)
            U(nod * 2, st, mij, pos, val);
        else
            U(nod * 2 + 1, mij + 1, dr, pos, val);
        aint[nod] = max(aint[nod * 2], aint[nod * 2 + 1]);
    }

    void Q(int nod, int st, int dr, int sti, int dri)
    {
        if(sti <= st && dr <= dri)
        {
            ans = max(ans, aint[nod]);
            return;
        }

        int mij = st + (dr - st) / 2;
        if(sti <= mij)
            Q(nod * 2, st, mij, sti, dri);
        if(mij < dri)
            Q(nod * 2 + 1, mij + 1, dr, sti, dri);
    }

public:
    void set_aint(int _ind, int _N)
    {
        ind = _ind;
        N = _N;
        aint = new int[4 * N];
        B(1, 1, N);
    }

    void U(int pos, int val)
    {
        U(1, 1, N, pos, val);
    }

    int Q(int sti, int dri)
    {
        ans = 0;
        Q(1, 1, N, sti, dri);
        return ans;
    }

    int Q(int pos)
    {
        ans = 0;
        Q(1, 1, N, pos, pos);
        return ans;
    }
}aint[100005];

int Q(int x, int y)
{
    if(lant[x] == lant[y])
    {
        int posx = pos[x];
        int posy = pos[y];
        if(posx > posy) swap(posx, posy);
        return aint[ lant[x] ].Q(posx, posy);
    }

    int n = lnt[ lant[x] ].size();
    int ans = aint[ lant[x] ].Q(pos[x], n);
    int ansnxt = Q(fth[ lnt[ lant[x] ][n - 1] ], y);
    return max(ans, ansnxt);
}

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

    N = gint();
    M = gint();
    for(int i = 1; i <= N; i++)
        val[i] = gint();
    for(int i = 1; i < N; i++)
    {
        int x, y;
        x = gint();
        y = gint();
        edg[x].push_back(y);
        edg[y].push_back(x);
    }

    DFS(1, 0);
    for(int i = 2; i <= E; i++)
    {
        p2[i] = p2[i - 1];
        if((2 << p2[i]) == i)
            p2[i]++;
    }

    for(int j = 1; (1 << j) <= E; j++)
        for(int i = 1; i + (1 << j) - 1 <= E; i++)
            rmq[i][j] = minh(rmq[i][j - 1], rmq[i + (1 << (j - 1))][j - 1]);

    for(int i = 1; i <= L; i++)
    {
        sort(lnt[i].begin(), lnt[i].end(), cmph);
        int n = lnt[i].size();
        for(int j = 0; j < lnt[i].size(); j++)
        {
            int nod = lnt[i][j];
            pos[nod] = j + 1;
        }
        aint[i].set_aint(i, n);
    }

    while(M--)
    {
        int op, x, y;
        op = gint();
        x = gint();
        y = gint();
        if(op == 0)
        {
            int lantx = lant[x];
            int posx = pos[x];
            aint[lantx].U(posx, y);
        }
        else
        {
            int lca = LCA(x, y);
            int q1 = Q(x, lca);
            int q2 = Q(y, lca);
            printf("%d\n", max(q1, q2));
        }
    }

    return 0;
}