Cod sursa(job #2447833)

Utilizator alextodoranTodoran Alexandru Raul alextodoran Data 14 august 2019 20:32:54
Problema Heavy Path Decomposition Scor 10
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.84 kb
#include <bits/stdc++.h>

using namespace std;

const int N_MAX = 100002;
const int M_MAX = 100002;

int n, m;

int val[N_MAX];

vector <int> edges[N_MAX];

int heavySon[N_MAX];

int parent[N_MAX];

int subSize[N_MAX];

bool visited[N_MAX];

vector <int> paths[N_MAX];
int cntPaths;

int pathIndex[N_MAX];
int pos[N_MAX];

short int pathLevel[N_MAX];

void dfs (int node)
{
    visited[node] = true;
    subSize[node] = 1;
    int maxSize = 0;
    for(int u : edges[node])
        if(visited[u] == false)
        {
            parent[u] = node;
            dfs(u);
            subSize[node] += subSize[u];
            if(subSize[u] > maxSize)
            {
                maxSize = subSize[u];
                heavySon[node] = u;
            }
        }

}

void heavy (int node)
{
    visited[node] = true;
    pathIndex[node] = cntPaths;
    pos[node] = paths[cntPaths].size();
    paths[cntPaths].push_back(node);
    if(heavySon[node] != 0)
        heavy(heavySon[node]);
    for(int u : edges[node])
        if(visited[u] == false && u != heavySon[node])
        {
            cntPaths++;
            pathLevel[cntPaths] = pathLevel[pathIndex[node]] + 1;
            heavy(u);
        }
}

vector <int> aint[N_MAX];

void build (int index, int node, int l, int r)
{
    if(l == r)
    {
        aint[index][node] = val[paths[index][l]];
        return;
    }
    int mid = (l + r) / 2, lson = (node << 1), rson = (lson | 1);
    build(index, lson, l, mid);
    build(index, rson, mid + 1, r);
    aint[index][node] = max(aint[index][lson], aint[index][rson]);
}

void update (int index, int node, int l, int r, int upos, int uval)
{
    if(l == r)
    {
        aint[index][node] = uval;
        return;
    }
    int mid = (l + r) / 2, lson = (node << 1), rson = (lson | 1);
    if(upos <= mid)
        update(index, lson, l, mid, upos, uval);
    else
        update(index, rson, mid + 1, r, upos, uval);
    aint[index][node] = max(aint[index][lson], aint[index][rson]);
}

int query (int index, int node, int l, int r, int ql, int qr)
{
    if(ql <= l && r <= qr)
        return aint[index][node];
    int mid = (l + r) / 2, lson = (node << 1), rson = (lson | 1);
    int val1 = 0, val2 = 0;
    if(ql <= mid)
        val1 = query(index, lson, l, mid, ql, qr);
    if(mid + 1 <= qr)
        val2 = query(index, rson, mid + 1, r, ql, qr);
    return max(val1, val2);
}

int main()
{
    ifstream fin ("heavypath.in");
    ofstream fout ("heavypath.out");
    fin >> n >> m;
    for(int i = 1; i <= n; i++)
        fin >> val[i];
    for(int i = 1; i < n; i++)
    {
        int u, v;
        fin >> u >> v;
        edges[u].push_back(v);
        edges[v].push_back(u);
    }
    dfs(1);
    memset(visited, false, sizeof(visited));
    cntPaths = 1;
    heavy(1);
    for(int i = 1; i <= cntPaths; i++)
    {
        aint[i].resize(4 * paths[i].size());
        build(i, 1, 0, paths[i].size() - 1);
    }
    while(m--)
    {
        int op;
        fin >> op;
        if(op == 0)
        {
            int node, uval;
            fin >> node >> uval;
            update(pathIndex[node], 1, 0, paths[pathIndex[node]].size() - 1, pos[node], uval);
        }
        else
        {
            int u, v;
            fin >> u >> v;
            int uPath = pathIndex[u];
            int vPath = pathIndex[v];
            int answer = 0;
            if(uPath == vPath)
                answer = query(uPath, 1, 0, paths[uPath].size() - 1, min(pos[u], pos[v]), max(pos[u], pos[v]));
            else
            {
                answer = max(answer, query(vPath, 1, 0, paths[vPath].size() - 1, 0, pos[v]));
                answer = max(answer, query(uPath, 1, 0, paths[uPath].size() - 1, 0, pos[u]));
            }
            while(uPath != vPath)
            {
                if(pathLevel[uPath] < pathLevel[vPath])
                {
                    v = parent[paths[vPath][0]];
                    vPath = pathIndex[v];
                    if(uPath == vPath)
                        answer = max(answer, query(uPath, 1, 0, paths[uPath].size() - 1, min(pos[u], pos[v]), max(pos[u], pos[v])));
                    else
                        answer = max(answer, query(vPath, 1, 0, paths[vPath].size() - 1, 0, pos[v]));
                }
                else
                {
                    u = parent[paths[uPath][0]];
                    uPath = pathIndex[u];
                    if(uPath == vPath)
                        answer = max(answer, query(uPath, 1, 0, paths[uPath].size() - 1, min(pos[u], pos[v]), max(pos[u], pos[v])));
                    else
                        answer = max(answer, query(uPath, 1, 0, paths[uPath].size() - 1, 0, pos[u]));
                }
            }
            fout << answer << "\n";
        }
    }
    return 0;
}