Cod sursa(job #1040859)

Utilizator sziliMandici Szilard szili Data 25 noiembrie 2013 00:41:40
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 6.68 kb
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>

#define MAX_N 100001

using namespace std;

typedef struct node{
    int val;
    int leftIndex, rightIndex;

    struct node *left;
    struct node *right;
} NODE;

typedef struct path{
    vector<int> nodes;
    int parentVal;
    NODE *associatedIntervalTree;
} PATH;

vector<PATH> paths;

int whatPath[MAX_N];
int whatPos[MAX_N];

int n,m;
int val[MAX_N];

int visited[MAX_N];
vector<int> adjacencyList[MAX_N];
int depths[MAX_N];

int dfs(int node, int currentDepth){
    int isLeaf = 1;

    visited[node] = 1;
    depths[node] = currentDepth;

    vector<int> childPathIndices;
    int pathIndexWithMaxNodes;
    int maxNodes = -1;
    int nrOfNodes = 1;

    for (int i=0; i<adjacencyList[node].size(); i++){
        int nextNode = adjacencyList[node][i];

        if (!visited[nextNode]){
            isLeaf = 0;

            int nodesNr = dfs(nextNode, currentDepth+1);
            nrOfNodes += nodesNr;

            int pathIndex = whatPath[nextNode];
            childPathIndices.push_back(pathIndex);

            if (nodesNr > maxNodes){
                maxNodes = nodesNr;
                pathIndexWithMaxNodes = pathIndex;
            }
        }
    }

    if (isLeaf){
        PATH p;
        p.nodes.push_back(node);
        p.parentVal = -1;
        whatPath[node] = paths.size();
        paths.push_back(p);
    }
     else {
        whatPath[node] = pathIndexWithMaxNodes;
        paths[pathIndexWithMaxNodes].nodes.push_back(node);

        for (int i=0; i<childPathIndices.size(); i++){
            int pathIndex = childPathIndices[i];

            if (pathIndex != whatPath[node]){
                PATH currentPath = paths[pathIndex];
                currentPath.parentVal = node;
                paths[pathIndex] = currentPath;
            }
        }
    }

    return nrOfNodes;
}

void makePaths(){
    int swapp;

    //we need to reverse the nodes order inside the paths and update the index within a path of the nodes
    for (int i=0; i<paths.size(); i++){
        int pathNodesSize = paths[i].nodes.size();

        for (int j=0; j <= ((pathNodesSize-1)/2); j++){
            swapp = paths[i].nodes[j];
            paths[i].nodes[j] = paths[i].nodes[(pathNodesSize-1 - j)];
            paths[i].nodes[(pathNodesSize-1 - j)] = swapp;

            whatPos[paths[i].nodes[j]] = j;
            whatPos[paths[i].nodes[(pathNodesSize-1 - j)]] = (pathNodesSize-1 - j);
        }
    }
}

int maxx(int val1, int val2){
    if (val1 > val2){
        return val1;
    } else {
        return val2;
    }
}

int minn(int val1, int val2){
    if (val1 < val2){
        return val1;
    } else {
        return val2;
    }
}


NODE * initTree(const vector<int> &nodes, int left, int right){

    if (left == right){
        NODE *p = (NODE *) malloc(sizeof(NODE));
        p->left = NULL;
        p->right = NULL;
        p->val = val[nodes[left]];

        p->leftIndex = left;
        p->rightIndex = right;

        return p;
    }

    int mid = (left + right)/2;
    NODE *p = (NODE *) malloc(sizeof(NODE));

    p->leftIndex = left;
    p->rightIndex = right;
    p->left = initTree(nodes, left, mid);
    p->right = initTree(nodes, mid+1, right);

    p->val = maxx(p->left->val, p->right->val);

    return p;
}

void initIntervalTrees(){
    for (int i=0; i<paths.size(); i++){
        PATH currentPath = paths[i];
        currentPath.associatedIntervalTree = initTree(currentPath.nodes, 0, currentPath.nodes.size()-1);
        paths[i]  = currentPath;
    }
}

NODE *updateIntervalTree(NODE *p, int pos, int newVal){
    if (p->leftIndex == p->rightIndex){
        p->val = newVal;
        return p;
    }

    int mid = (p->leftIndex + p->rightIndex)/2;
    if (pos <= mid){
        p->left = updateIntervalTree(p->left, pos, newVal);
    } else {
        p->right = updateIntervalTree(p->right, pos, newVal);
    }

    p->val = maxx(p->left->val, p->right->val);

    return p;
}

int intersects(int left1, int right1, int left2, int right2){
    int doesntIntersect = (right1< left2) || (right2 < left1);

    return !doesntIntersect;
}

int queryIT(NODE *p, int left, int right){
    int maxVal = -1;
    if (p->leftIndex >= left && p->rightIndex <= right){
        return p->val;
    }

    int mid = (p->leftIndex + p->rightIndex)/2;

    if (intersects(p->leftIndex, mid, left, right)){
        maxVal = queryIT(p->left, left, right);
    }

    if (intersects(mid, p->rightIndex, left, right)){
        int currentVal = queryIT(p->right, left, right);

        maxVal = maxx(currentVal, maxVal);
    }

    return maxVal;
}


int query(int x, int y){
    int swapp;
    int maxValue = -1;
    int finished = 0;

    while (!finished){
        if (whatPath[x] == whatPath[y]){
            int minIndex = minn(whatPos[x], whatPos[y]);
            int maxIndex = maxx(whatPos[x], whatPos[y]);

            int currentVal = queryIT(paths[whatPath[x]].associatedIntervalTree, minIndex, maxIndex);
            maxValue = maxx(maxValue, currentVal);

            finished = 1;
        } else {
            if (depths[paths[whatPath[x]].parentVal] <  depths[paths[whatPath[y]].parentVal]){
                swapp = x;
                x = y;
                y = swapp;
            }

            int currentVal = queryIT(paths[whatPath[x]].associatedIntervalTree, 0, whatPos[x]);
            maxValue = maxx(currentVal, maxValue);
            x = paths[whatPath[x]].parentVal;
        }
    }

    return maxValue;
}

void solve(){
    int operation,x,y;

    while (scanf("%d %d %d", &operation, &x, &y) != EOF){
        if (operation == 0){ //operation 0 (update)
            PATH path = paths[whatPath[x]];

            path.associatedIntervalTree = updateIntervalTree(path.associatedIntervalTree, whatPos[x], y);
            val[x] = y;
        }
        else { //operation 1 (query)
            int maxValueOnPath = query(x,y);

            printf("%d\n", maxValueOnPath);
        }
    }

}

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

    scanf("%d %d", &n, &m);

    int currentVal;
    for (int i=1; i<=n; i++){
        scanf("%d", &currentVal);
        val[i] = currentVal;
    }

    int nod1, nod2;
    for (int i=0; i<n-1; i++){
        scanf("%d %d", &nod1, &nod2);
        adjacencyList[nod1].push_back(nod2);
        adjacencyList[nod2].push_back(nod1);
    }

    //suppose 1 is the roots
    dfs(1, 1);

    makePaths();
    initIntervalTrees();

    solve();

    return 0;
}