Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <fstream>
- #include <climits>
- #include <vector>
- #include <algorithm>
- #include <set>
- using namespace std;
- ifstream fin("minonpath.in");
- ofstream fout("minonpath.out");
- int max_deep, cur_time, N;
- struct node {
- int deep, time_in, time_out,number;
- vector<int> links;
- int back_link, price=INT_MAX;
- node *left = nullptr;
- node *right = nullptr;
- node *head = nullptr;
- int L, R;
- node(int L, int R) : L(L), R(R) {};
- node()= default;
- };
- vector<node *> base;
- vector<int> ndo;
- inline bool is_on_line(int first,int second){
- return base[first]->time_out>=base[second]->time_out&&base[first]->time_in<=base[second]->time_in;
- }
- inline int LCA(int first, int second) {
- while (first != second) {
- if (base[first]->deep > base[second]->deep) {
- first = base[first]->back_link;
- } else if (base[first]->deep < base[second]->deep) {
- second = base[second]->back_link;
- } else if (base[first]->deep == base[second]->deep) {
- first = base[first]->back_link;
- second = base[second]->back_link;
- }
- }
- return first;
- }
- int build_tree(int deep, int current_deep, node *¤t, node *head) {
- if (current_deep != deep) {
- current->left = new node(current->L, (current->L + current->R) / 2);
- current->right = new node((current->L + current->R) / 2 + 1, current->R);
- current->price = min(build_tree(deep, current_deep + 1, current->left, head),
- build_tree(deep, current_deep + 1, current->right, head));
- return current->price;
- }
- else{
- if (N < ndo.size()) {
- int L=current->L,R=current->R;
- current = base[ndo[N]];
- current->R=R;
- current->L=L;
- base[ndo[N]]->head = head;
- N++;
- return base[ndo[N-1]]->price;
- } else {
- return INT_MAX;
- }
- }
- }
- inline void build() {
- N = 0;
- int deep = 0;
- while (((1 << deep)) < ndo.size()) {
- deep++;
- }
- node *tmp = new node(base[ndo[0]]->deep, base[ndo[0]]->deep+(1 << deep)-1);
- build_tree(deep, 0, tmp, tmp);
- }
- void do_HLD(int cur = 0) {
- ndo.push_back(cur);
- if (base[cur]->links.size()) {
- int max_link = INT_MAX, ml = -1;
- for (int i = 0; i < base[cur]->links.size(); i++) {
- if (max_link > base[base[cur]->links[i]]->time_out - base[base[cur]->links[i]]->time_in){
- ml = i;
- max_link=base[base[cur]->links[i]]->time_out - base[base[cur]->links[i]]->time_in;}
- }
- swap(base[cur]->links[0], base[cur]->links[ml]);
- do_HLD(base[cur]->links[0]);
- for (int i = 1; i < base[cur]->links.size(); i++) {
- do_HLD(base[cur]->links[i]);
- }
- } else {
- build();
- ndo.resize(0);
- }
- }
- void dfs(int cur = 0, int deep = 0) {
- base[cur]->deep = deep;
- base[cur]->time_in = cur_time;
- for (int i = 0; i < base[cur]->links.size(); i++) {
- dfs(base[cur]->links[i], deep + 1);
- cur_time++;
- }
- base[cur]->time_out = cur_time;
- }
- pair<int,int> do_min(int L,int R,node* current){
- if(L<=current->L&&R>=current->R)
- return make_pair(current->number,current->price);
- if(L>current->R||R<current->L)
- return make_pair(-1,INT_MAX);
- pair<int,int> tmp=do_min(L,R,current->left);
- tmp.second=min(tmp.second,do_min(L,R,current->right).second);
- return tmp;
- };
- inline int get(int up,int down){
- int min_price=INT_MAX;
- pair<int,int> tmp;
- while(up!=down){
- if(base[down]->head->L-1>=base[up]->deep){
- tmp=do_min(base[down]->head->L,base[down]->deep,base[down]->head);
- down=base[tmp.first]->back_link;
- min_price=min(min_price,tmp.second);
- }
- else{
- min_price=min(min_price,do_min(base[up]->deep+1,base[down]->deep,base[down]->head).second);
- down=up;
- }
- }
- return min_price;
- }
- inline int get_min(int first,int second){
- if(is_on_line(first,second))
- return get(first,second);
- if(is_on_line(second,first))
- return get(second,first);
- int L=LCA(first,second);
- return min(get(L,second),get(L,first));
- }
- int main() {
- ios_base::sync_with_stdio(false);
- int n, tmp, price;
- fin >> n;
- while ((1 << max_deep) <= n) max_deep++;
- base.resize(n);
- int i =0;
- for (node *&el:base) {
- el = new node();
- el->number=i;
- i++;
- }
- for (int i = 1; i < n; i++) {
- fin >> tmp >> price;
- base[tmp - 1]->links.push_back(i);
- base[i]->back_link = tmp - 1;
- base[i]->price = price;
- }
- dfs();
- do_HLD();
- fin >> tmp;
- int first, second;
- for (int i = 0; i < tmp; i++) {
- fin >> first >> second;
- fout << get_min(first-1,second-1) << endl;
- }
- fin.close();
- fout.close();
- }
Advertisement
Add Comment
Please, Sign In to add comment