Cod sursa(job #1336163)

Utilizator okros_alexandruOkros Alexandru okros_alexandru Data 6 februarie 2015 20:37:17
Problema Heavy Path Decomposition Scor 80
Compilator cpp Status done
Runda Arhiva educationala Marime 5.18 kb
#include <fstream>
#include <iostream>
#include <vector>

#define Nmax 100100
#define Tmax 400400
#define son Tree[node][i]

using namespace std;

struct {
    int value, father, level, sons, stripeId, position;
    } Data[Nmax];

vector <int> Tree[Nmax], Stripe[Nmax];
int N, countStripes;

class segmentTrees {

    #define root 1
    #define leftSon (node << 1)
    #define rightSon ((node << 1) | 1)
    #define middle ((left + right) >> 1)

    private:
        int top, tree[Tmax], start[Nmax], end[Nmax], size[Nmax];

        void build(int node, int left, int right, int offset, vector <int> & stripe) {

            if(left == right) {
                tree[node + offset] = Data[stripe[left - 1]].value;
                return;
            }

            build(leftSon, left, middle, offset, stripe);
            build(rightSon, middle + 1, right, offset, stripe);

            if(tree[leftSon + offset] > tree[rightSon + offset])
                tree[node + offset] = tree[leftSon + offset];
            else
                tree[node + offset] = tree[rightSon + offset];
        }

        void update(int node, int left, int right, int offset, int & index, int & value) {

            if(left == right) {
                tree[node + offset] = value;
                return;
            }

            if(index <= middle)
                update(leftSon, left, middle, offset, index, value);
            else
                update(rightSon, middle + 1, right, offset, index, value);

            if(tree[leftSon + offset] > tree[rightSon + offset])
                tree[node + offset] = tree[leftSon + offset];
            else
                tree[node + offset] = tree[rightSon + offset];
        }

        int query(int node, int left, int right, int offset, int & a, int & b) {

            if(a <= left && right <= b)
                return tree[node + offset];

            int result = 0;

            if(a <= middle)
                result = query(leftSon, left, middle, offset, a, b);
            if(middle < b)
                result = max(result, query(rightSon, middle + 1, right, offset, a, b));

            return result;
        }

    public:
        segmentTrees() {
            top = 0;
            end[0] = 0;
        }

        void create(vector <int> & stripe) {

            size[++top] = stripe.size();
            start[top] = end[top - 1] + 1;
            end[top] = start[top] + (size[top] << 2);

            build(root, 1, size[top], start[top] - 1, stripe);
        }

        void update(int & node, int & newValue) {
            Data[node].value = newValue;
            update(root, 1, size[Data[node].stripeId], start[Data[node].stripeId] - 1, Data[node].position, newValue);
        }

        int query(int & nodeA, int & nodeB) {

            int a, b, id, result = 0;

            while(Data[nodeA].stripeId != Data[nodeB].stripeId) {

                if(Data[Data[Stripe[Data[nodeA].stripeId].back()].father].level
                   > Data[Data[Stripe[Data[nodeB].stripeId].back()].father].level)
                    swap(nodeA, nodeB);

                result = max(result, query(root, 1, size[Data[nodeB].stripeId], start[Data[nodeB].stripeId] - 1, Data[nodeB].position, size[Data[nodeB].stripeId]));
                nodeB = Data[Stripe[Data[nodeB].stripeId].back()].father;
            }

            id = Data[nodeA].stripeId;
            a = Data[nodeA].position;
            b = Data[nodeB].position;

            if(a > b)
                swap(a, b);

            return max(result, query(root, 1, size[id], start[id] - 1, a, b));
        }

} sts;

void Dfs(int node, int father, int level) {

    int i, one = 0;

    Data[node].father = father;
    Data[node].level = level;
    Data[node].sons = 1;

    for(i = 0; i < Tree[node].size(); i++)
        if(son != father) {

            Dfs(son, node, level + 1);
            Data[node].sons += Data[son].sons;

            if(Data[son].sons > Data[one].sons)
                one = son;
        }

    if(Data[node].sons == 1) {
        Stripe[++countStripes].push_back(node);
        Data[node].stripeId = countStripes;
        Data[node].position = 1;
    }
    else {
        Stripe[Data[one].stripeId].push_back(node);
        Data[node].stripeId = Data[one].stripeId;
        Data[node].position = Stripe[Data[one].stripeId].size();
    }

}
void Prepare() {

    Dfs(1, 0, 1);

    for(int i = 1; i <= countStripes; i++)
        sts.create(Stripe[i]);

}
void Read(ifstream & in, int & queries) {

    int i, x, y;

    in >> N >> queries;

    for(i = 1; i <= N; i++)
        in >> Data[i].value;

    for(i = 1; i < N; i++) {
        in >> x >> y;
        Tree[x].push_back(y);
        Tree[y].push_back(x);
    }

}
int main() {

    int x, y, type, queries;
    ifstream in("heavypath.in");
    ofstream out("heavypath.out");

    Read(in, queries);
    Prepare();

    while(queries--) {

        in >> type >> x >> y;

        if(type == 0)
            sts.update(x, y);
        else
            out << sts.query(x, y) << '\n';

    }

    in.close();
    out.close();

    return 0;
}