Cod sursa(job #1660352)

Utilizator bogdan10bosBogdan Sitaru bogdan10bos Data 22 martie 2016 23:51:34
Problema Heavy Path Decomposition Scor 40
Compilator cpp Status done
Runda Arhiva educationala Marime 4.79 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, ans;
int Nlant[100005];
int hvy[100005], val[100005];
int h[100005], poseul[100005];
int E, rmq[200005][18], 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]);
}

int *aint[100005];

void B(int ind, int nod, int st, int dr)
{
    if(st == dr)
    {
        aint[ind][nod] = val[ lnt[ind][st - 1] ];
        return;
    }
    int mij = st + (dr - st) / 2;
    B(ind, nod * 2, st, mij);
    B(ind, nod * 2 + 1, mij + 1, dr);
    aint[ind][nod] = max(aint[ind][nod * 2], aint[ind][nod * 2 + 1]);
}

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

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

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

int Query(int x, int y)
{
    if(lant[x] == lant[y])
    {
        int posx = pos[x];
        int posy = pos[y];
        if(posx > posy) swap(posx, posy);
        ans = 0;
        Q(lant[x], 1, 1, Nlant[ lant[x] ], posx, posy);
        return ans;
    }

    int n = lnt[ lant[x] ].size();
    ans = 0;
    Q(lant[x], 1, 1, Nlant[ lant[x] ], pos[x], Nlant[ lant[x] ]);
    int ans1 = ans;
    int ansnxt = Query(fth[ lnt[ lant[x] ][n - 1] ], y);
    return max(ans1, 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++)
    {
        Nlant[i] = lnt[i].size();
        sort(lnt[i].begin(), lnt[i].end(), cmph);
        for(int j = 0; j < lnt[i].size(); j++)
        {
            int nod = lnt[i][j];
            pos[nod] = j + 1;
        }

        aint[i] = new int[ Nlant[i] * 4 ];
        B(i, 1, 1, Nlant[i]);
    }

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

    return 0;
}