Cod sursa(job #1569405)

Utilizator usermeBogdan Cretu userme Data 15 ianuarie 2016 15:07:55
Problema Heavy Path Decomposition Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 3.78 kb
#include <stdio.h>
#include <assert.h>
#include <vector>
#include <queue>
#include <algorithm>

using std::vector;
using std::queue;
using std::swap;
using std::max;

const int MAX_N = 100000;

int N, M;

int v[1 + MAX_N];
int father[1 + MAX_N];
vector<int> sons[1 + MAX_N];
vector<int> g[1 + MAX_N];

int maxim[MAX_N];

struct Node;

struct Chain {
  Node* top;
  int size;
  int offset;

  Chain() {
    this->top = NULL;
    this->size = 0;
    this->offset = 0;
  }

  void setValue(int index, int value) {
    maxim[this->offset + index] = value;
  }

  int getMax(int a, int b) {
    int i;
    int answer = 0;
    for (i = a; i <= b; i++) {
      answer = max(answer, maxim[this->offset + i]);
    }
    return answer;
  }
};

struct Node {
  int index;
  Node *father;
  int weight;
  int depth;
  int chainPosition;
  Chain *chain;
};

Node nodes[1 + MAX_N];
int chainsCount = 0;
Chain chains[1 + MAX_N];

void dfs2(int node, int nodeFather = 0) {
  for (int neighbour : g[node]) {
    if (neighbour != nodeFather) {
      father[neighbour] = node;
      sons[node].push_back(neighbour);
      dfs2(neighbour, node);
    }
  }
}

void dfs(int node) {
  nodes[node].index = node;
  nodes[node].weight = 1;
  int maxWeightNode = 0;
  for (int son : sons[node]) {
    nodes[son].depth = nodes[node].depth + 1;
    nodes[son].father = &nodes[node];
    dfs(son);
    nodes[node].weight += nodes[son].weight;
    if (nodes[maxWeightNode].weight < nodes[son].weight) {
      maxWeightNode = son;
    }
  }
  if (maxWeightNode != 0) {
    nodes[node].chain = nodes[maxWeightNode].chain;
    nodes[node].chainPosition = nodes[maxWeightNode].chainPosition + 1;
  } else {
    nodes[node].chain = &chains[chainsCount++];
    nodes[node].chainPosition = 0;
  }
  nodes[node].chain->size++;
  nodes[node].chain->top = &nodes[node];
}

void print(int node, int offset = 0) {
  int i;
  for (i = 0; i < offset; i++) {
    printf("  ");
  }
  printf("%d: %d %d %d\n",
      nodes[node].index,
      nodes[node].depth,
      nodes[node].weight,
      nodes[node].chain->top->index);
  for (int son : sons[node]) {
    print(son, offset + 1);
  }
}

int lca(int a, int b) {
  while (nodes[a].chain != nodes[b].chain) {
    if (nodes[a].chain->top->depth < nodes[b].chain->top->depth) {
      swap(a, b);
    }
    a = nodes[a].chain->top->father->index;
  }
  if (nodes[a].depth < nodes[b].depth) {
    return a;
  } else {
    return b;
  }
}

int getMax(int a, int b) {
  int answer = 0;
  while (nodes[a].chain != nodes[b].chain) {
    if (nodes[a].chain->top->depth < nodes[b].chain->top->depth) {
      swap(a, b);
    }
    answer = max(answer, nodes[a].chain->getMax(
        nodes[a].chainPosition, nodes[a].chain->top->chainPosition));
    a = nodes[a].chain->top->father->index;
  }
  if (nodes[b].depth < nodes[a].depth) {
    answer = max(answer, nodes[a].chain->getMax(
        nodes[a].chainPosition, nodes[b].chainPosition));
  } else {
    answer = max(answer, nodes[a].chain->getMax(
        nodes[b].chainPosition, nodes[a].chainPosition));
  }
  return answer;
}

int main() {
  int i;
  freopen("heavypath.in", "r", stdin);
  freopen("heavypath.out", "w", stdout);
  scanf("%d %d", &N, &M);
  for (i = 1; i <= N; i++) {
    scanf("%d", &v[i]);
  }
  for (i = 2; i <= N; i++) {
    int a, b;
    scanf("%d %d", &a, &b);
    g[a].push_back(b);
    g[b].push_back(a);
  }
  dfs2(1);
  dfs(1);
  int val = 0;
  for (i = 0; i < chainsCount; i++) {
    chains[i].offset = val;
    val += chains[i].size;
  }
  for (i = 1; i <= N; i++) {
    nodes[i].chain->setValue(nodes[i].chainPosition, v[i]);
  }
  //print(1);

  //*
  for (i = 1; i <= M; i++) {
    int t, x, y;
    scanf("%d %d %d", &t, &x, &y);
    if (t == 0) {
      nodes[x].chain->setValue(nodes[x].chainPosition, y);
    } else { // t == 1
      printf("%d\n", getMax(x, y));
    }
  }//*/
  return 0;
}