ivolff

HLD

May 23rd, 2018
171
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.00 KB | None | 0 0
  1. #include <iostream>
  2. #include <fstream>
  3. #include <climits>
  4. #include <vector>
  5. #include <algorithm>
  6. #include <set>
  7.  
  8. using namespace std;
  9.  
  10. ifstream fin("minonpath.in");
  11. ofstream fout("minonpath.out");
  12.  
  13. int max_deep, cur_time, N;
  14.  
  15. struct node {
  16.     int deep, time_in, time_out,number;
  17.     vector<int> links;
  18.     int back_link, price=INT_MAX;
  19.     node *left = nullptr;
  20.     node *right = nullptr;
  21.     node *head = nullptr;
  22.     int L, R;
  23.  
  24.     node(int L, int R) : L(L), R(R) {};
  25.  
  26.     node()= default;
  27. };
  28.  
  29.  
  30. vector<node *> base;
  31.  
  32. vector<int> ndo;
  33.  
  34. inline bool is_on_line(int first,int second){
  35.     return base[first]->time_out>=base[second]->time_out&&base[first]->time_in<=base[second]->time_in;
  36. }
  37.  
  38. inline int LCA(int first, int second) {
  39.     while (first != second) {
  40.         if (base[first]->deep > base[second]->deep) {
  41.             first = base[first]->back_link;
  42.         } else if (base[first]->deep < base[second]->deep) {
  43.             second = base[second]->back_link;
  44.         } else if (base[first]->deep == base[second]->deep) {
  45.             first = base[first]->back_link;
  46.             second = base[second]->back_link;
  47.         }
  48.     }
  49.     return first;
  50. }
  51.  
  52. int build_tree(int deep, int current_deep, node *&current, node *head) {
  53.     if (current_deep != deep) {
  54.         current->left = new node(current->L, (current->L + current->R) / 2);
  55.         current->right = new node((current->L + current->R) / 2 + 1, current->R);
  56.         current->price = min(build_tree(deep, current_deep + 1, current->left, head),
  57.                                  build_tree(deep, current_deep + 1, current->right, head));
  58.         return current->price;
  59.     }
  60.     else{
  61.         if (N < ndo.size()) {
  62.             int L=current->L,R=current->R;
  63.             current = base[ndo[N]];
  64.             current->R=R;
  65.             current->L=L;
  66.             base[ndo[N]]->head = head;
  67.             N++;
  68.             return base[ndo[N-1]]->price;
  69.         } else {
  70.             return INT_MAX;
  71.         }
  72.     }
  73. }
  74.  
  75.  
  76. inline void build() {
  77.     N = 0;
  78.     int deep = 0;
  79.     while (((1 << deep)) < ndo.size()) {
  80.         deep++;
  81.     }
  82.     node *tmp = new node(base[ndo[0]]->deep, base[ndo[0]]->deep+(1 << deep)-1);
  83.     build_tree(deep, 0, tmp, tmp);
  84. }
  85.  
  86. void do_HLD(int cur = 0) {
  87.     ndo.push_back(cur);
  88.     if (base[cur]->links.size()) {
  89.         int max_link = INT_MAX, ml = -1;
  90.         for (int i = 0; i < base[cur]->links.size(); i++) {
  91.             if (max_link > base[base[cur]->links[i]]->time_out - base[base[cur]->links[i]]->time_in){
  92.                 ml = i;
  93.                 max_link=base[base[cur]->links[i]]->time_out - base[base[cur]->links[i]]->time_in;}
  94.         }
  95.         swap(base[cur]->links[0], base[cur]->links[ml]);
  96.         do_HLD(base[cur]->links[0]);
  97.         for (int i = 1; i < base[cur]->links.size(); i++) {
  98.             do_HLD(base[cur]->links[i]);
  99.         }
  100.     } else {
  101.         build();
  102.         ndo.resize(0);
  103.     }
  104. }
  105.  
  106. void dfs(int cur = 0, int deep = 0) {
  107.     base[cur]->deep = deep;
  108.     base[cur]->time_in = cur_time;
  109.     for (int i = 0; i < base[cur]->links.size(); i++) {
  110.         dfs(base[cur]->links[i], deep + 1);
  111.         cur_time++;
  112.     }
  113.     base[cur]->time_out = cur_time;
  114. }
  115.  
  116. pair<int,int> do_min(int L,int R,node* current){
  117.     if(L<=current->L&&R>=current->R)
  118.         return make_pair(current->number,current->price);
  119.     if(L>current->R||R<current->L)
  120.         return make_pair(-1,INT_MAX);
  121.     pair<int,int> tmp=do_min(L,R,current->left);
  122.     tmp.second=min(tmp.second,do_min(L,R,current->right).second);
  123.     return tmp;
  124. };
  125.  
  126. inline int get(int up,int down){
  127.     int min_price=INT_MAX;
  128.     pair<int,int> tmp;
  129.     while(up!=down){
  130.         if(base[down]->head->L-1>=base[up]->deep){
  131.             tmp=do_min(base[down]->head->L,base[down]->deep,base[down]->head);
  132.             down=base[tmp.first]->back_link;
  133.             min_price=min(min_price,tmp.second);
  134.         }
  135.         else{
  136.             min_price=min(min_price,do_min(base[up]->deep+1,base[down]->deep,base[down]->head).second);
  137.             down=up;
  138.         }
  139.     }
  140.     return min_price;
  141. }
  142.  
  143. inline int get_min(int first,int second){
  144.     if(is_on_line(first,second))
  145.         return get(first,second);
  146.     if(is_on_line(second,first))
  147.         return get(second,first);
  148.     int L=LCA(first,second);
  149.     return min(get(L,second),get(L,first));
  150. }
  151.  
  152. int main() {
  153.     ios_base::sync_with_stdio(false);
  154.     int n, tmp, price;
  155.     fin >> n;
  156.     while ((1 << max_deep) <= n) max_deep++;
  157.     base.resize(n);
  158.     int i =0;
  159.     for (node *&el:base) {
  160.         el = new node();
  161.         el->number=i;
  162.         i++;
  163.     }
  164.     for (int i = 1; i < n; i++) {
  165.         fin >> tmp >> price;
  166.         base[tmp - 1]->links.push_back(i);
  167.         base[i]->back_link = tmp - 1;
  168.         base[i]->price = price;
  169.     }
  170.     dfs();
  171.     do_HLD();
  172.     fin >> tmp;
  173.     int first, second;
  174.     for (int i = 0; i < tmp; i++) {
  175.         fin >> first >> second;
  176.         fout << get_min(first-1,second-1) << endl;
  177.     }
  178.     fin.close();
  179.     fout.close();
  180. }
Advertisement
Add Comment
Please, Sign In to add comment