結果

問題 No.3194 Do Optimize Your Solution
コンテスト
ユーザー sumsumf
提出日時 2025-12-20 22:15:27
言語 C++17
(gcc 13.3.0 + boost 1.89.0)
結果
WA  
実行時間 -
コード長 27,672 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 6,251 ms
コンパイル使用メモリ 282,856 KB
実行使用メモリ 335,200 KB
最終ジャッジ日時 2025-12-20 22:16:13
合計ジャッジ時間 43,852 ms
ジャッジサーバーID
(参考情報)
judge5 / judge4
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample WA * 2
other RE * 12 TLE * 5
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

# pragma GCC optimize("O3")
#include<bits/stdc++.h>
using namespace std;
using uint=unsigned;
using ll=long long;
using ull=unsigned long long;
using ld=long double;
using i128=__int128;
constexpr int inf=1e9;
constexpr ll INF=2e18;
#define rep(i,n) for(ll i=0;i<ll(n);i++)
#define REP(i,n,m) for(ll i=(n);i<ll(m);i++)
#define DREP(i,n,m) for(ll i=(n);i>=ll(m);i--)
#define drep(i,n) for(ll i=ll(n)-1;i>=0;i--)
#define all(x) (x).begin(),(x).end()
#define rall(x) (x).rbegin(),(x).rend()
template<class T>using vc=vector<T>;
template<class T>using vvc=vc<vc<T>>;
template<class T>using vvvc=vc<vc<vc<T>>>;
template<class T>using vvvvc=vc<vc<vc<vc<T>>>>;
template<class T>using smpq=priority_queue<T,vc<T>,greater<T>>;
template<class T>using bipq=priority_queue<T>;
template<class T,class F>
int chmin(T&a,F b){
    if(a>b){
        a=b;
        return 1;
    }
    return 0;
}
template<class T,class F>
int chmax(T&a,F b){
    if(a<b){
        a=b;
        return 1;
    }
    return 0;
}
#ifndef ATCODER
// pair
template<typename T, typename U>
std::ostream& operator<<(std::ostream& os, const std::pair<T, U>& p) {
    return os << "(" << p.first << ", " << p.second << ")";
}
// vector
template<typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<T>& v) {
    os << "[";
    for (size_t i = 0; i < v.size(); ++i) {
        if (i > 0) os << ", ";
        os << v[i];
    }
    os << "]";
    return os;
}

// deque
template<typename T>
std::ostream& operator<<(std::ostream& os, const std::deque<T>& dq) {
    os << "[";
    for (size_t i = 0; i < dq.size(); ++i) {
        if (i > 0) os << ", ";
        os << dq[i];
    }
    os << "]";
    return os;
}

// list
template<typename T>
std::ostream& operator<<(std::ostream& os, const std::list<T>& lst) {
    os << "[";
    bool first = true;
    for (const auto& x : lst) {
        if (!first) os << ", ";
        os << x;
        first = false;
    }
    os << "]";
    return os;
}

// set
template<typename T>
std::ostream& operator<<(std::ostream& os, const std::set<T>& s) {
    os << "{";
    bool first = true;
    for (const auto& x : s) {
        if (!first) os << ", ";
        os << x;
        first = false;
    }
    os << "}";
    return os;
}

// unordered_set
template<typename T>
std::ostream& operator<<(std::ostream& os, const std::unordered_set<T>& s) {
    os << "{";
    bool first = true;
    for (const auto& x : s) {
        if (!first) os << ", ";
        os << x;
        first = false;
    }
    os << "}";
    return os;
}

// map
template<typename K, typename V>
std::ostream& operator<<(std::ostream& os, const std::map<K, V>& m) {
    os << "{";
    bool first = true;
    for (const auto& kv : m) {
        if (!first) os << ", ";
        os << kv;
        first = false;
    }
    os << "}";
    return os;
}

// unordered_map
template<typename K, typename V>
std::ostream& operator<<(std::ostream& os, const std::unordered_map<K, V>& m) {
    os << "{";
    bool first = true;
    for (const auto& kv : m) {
        if (!first) os << ", ";
        os << kv;
        first = false;
    }
    os << "}";
    return os;
}

// stack(コピーが必要)
template<typename T>
std::ostream& operator<<(std::ostream& os, std::stack<T> st) {
    os << "[";
    bool first = true;
    while (!st.empty()) {
        if (!first) os << ", ";
        os << st.top();
        st.pop();
        first = false;
    }
    os << "]";
    return os;
}

// queue(コピーが必要)
template<typename T>
std::ostream& operator<<(std::ostream& os, std::queue<T> q) {
    os << "[";
    bool first = true;
    while (!q.empty()) {
        if (!first) os << ", ";
        os << q.front();
        q.pop();
        first = false;
    }
    os << "]";
    return os;
}

// priority_queue(コピーが必要)
template<typename T>
std::ostream& operator<<(std::ostream& os, std::priority_queue<T> pq) {
    os << "[";
    bool first = true;
    while (!pq.empty()) {
        if (!first) os << ", ";
        os << pq.top();
        pq.pop();
        first = false;
    }
    os << "]";
    return os;
}

#define dbg(...) debug_func(0, #__VA_ARGS__, __VA_ARGS__)

template <typename T>
void debug_func(int i, T name) {
  cout << endl;
}

template <typename T1, typename T2, typename... T3>
void debug_func(int i, const T1 &name, const T2 &a, const T3 &...b) {
  for ( ; name[i] != ',' && name[i] != '\0'; i++ ) cout << name[i];
  cout << ":" << a << " ";
  debug_func(i + 1, name, b...);
}
#else
#define dbg(...) 123456789
#endif
template<class T>
vc<T>sorted(vc<T>v){
    sort(all(v));
    return v;
}
template<class T>
vc<T>reved(vc<T>v){
    reverse(all(v));
    return v;
}
template<class T>
vc<T>presum(vc<T>v){
    vc<T>res(v.size()+1);
    rep(i,v.size()){
      res[i+1]=res[i]+v[i];
    }
    return res;
}


template <typename T>
struct edge {
  int src, to;
  T cost;

  edge(int _to, T _cost) : src(-1), to(_to), cost(_cost) {}
  edge(int _src, int _to, T _cost) : src(_src), to(_to), cost(_cost) {}

  edge &operator=(const int &x) {
    to = x;
    return *this;
  }

  operator int() const { return to; }
};
template <typename T>
using Edges = vector<edge<T>>;
template <typename T>
using WeightedGraph = vector<Edges<T>>;
using UnweightedGraph = vector<vector<int>>;

// Input of (Unweighted) Graph
UnweightedGraph graph(int N, int M = -1, bool is_directed = false,
                      bool is_1origin = true) {
  UnweightedGraph g(N);
  if (M == -1) M = N - 1;
  for (int _ = 0; _ < M; _++) {
    int x, y;
    cin >> x >> y;
    if (is_1origin) x--, y--;
    g[x].push_back(y);
    if (!is_directed) g[y].push_back(x);
  }
  return g;
}

// Input of Weighted Graph
template <typename T>
WeightedGraph<T> wgraph(int N, int M = -1, bool is_directed = false,
                        bool is_1origin = true) {
  WeightedGraph<T> g(N);
  if (M == -1) M = N - 1;
  for (int _ = 0; _ < M; _++) {
    int x, y;
    cin >> x >> y;
    T c;
    cin >> c;
    if (is_1origin) x--, y--;
    g[x].emplace_back(x, y, c);
    if (!is_directed) g[y].emplace_back(y, x, c);
  }
  return g;
}

// Input of Edges
template <typename T>
Edges<T> esgraph([[maybe_unused]] int N, int M, int is_weighted = true,
                 bool is_1origin = true) {
  Edges<T> es;
  for (int _ = 0; _ < M; _++) {
    int x, y;
    cin >> x >> y;
    T c;
    if (is_weighted)
      cin >> c;
    else
      c = 1;
    if (is_1origin) x--, y--;
    es.emplace_back(x, y, c);
  }
  return es;
}

// Input of Adjacency Matrix
template <typename T>
vector<vector<T>> adjgraph(int N, int M, T INF, int is_weighted = true,
                           bool is_directed = false, bool is_1origin = true) {
  vector<vector<T>> d(N, vector<T>(N, INF));
  for (int _ = 0; _ < M; _++) {
    int x, y;
    cin >> x >> y;
    T c;
    if (is_weighted)
      cin >> c;
    else
      c = 1;
    if (is_1origin) x--, y--;
    d[x][y] = c;
    if (!is_directed) d[y][x] = c;
  }
  return d;
}

/**
 * @brief グラフテンプレート
 * @docs docs/graph/graph-template.md
 */

template <typename G>
struct Tree {
 private:
  G& g;
  int root;
  vector<array<int, 24>> bl;
  vector<int> dp;
  void build() {
    bl.resize(g.size());
    dp.resize(g.size());
    for (auto& v : bl) fill(begin(v), end(v), -1);
    dfs(root, -1, 0);
  }

  void dfs(int c, int p, int _dp) {
    dp[c] = _dp;
    for (int i = p, x = 0; i != -1;) {
      bl[c][x] = i;
      i = bl[i][x], x++;
    }
    for (auto& d : g[c]) {
      if (d == p) continue;
      dfs(d, c, _dp + 1);
    }
  }

 public:
  Tree(G& _g, int _r = 0) : g(_g), root(_r) { build(); }

  int depth(int u) const { return dp[u]; }

  int par(int u) const { return u == root ? -1 : bl[u][0]; }

  int kth_ancestor(int u, int k) const {
    if (dp[u] < k) return -1;
    while (k) {
      int t = __builtin_ctz(k);
      u = bl[u][t], k ^= 1 << t;
    }
    return u;
  }

  int nxt(int s, int t) const {
    if (dp[s] >= dp[t]) return par(s);
    int u = kth_ancestor(t, dp[t] - dp[s] - 1);
    return bl[u][0] == s ? u : bl[s][0];
  }

  vector<int> path(int s, int t) const {
    vector<int> pre, suf;
    while (dp[s] > dp[t]) {
      pre.push_back(s);
      s = bl[s][0];
    }
    while (dp[s] < dp[t]) {
      suf.push_back(t);
      t = bl[t][0];
    }
    while (s != t) {
      pre.push_back(s);
      suf.push_back(t);
      s = bl[s][0];
      t = bl[t][0];
    }
    pre.push_back(s);
    reverse(begin(suf), end(suf));
    copy(begin(suf), end(suf), back_inserter(pre));
    return pre;
  }

  int lca(int u, int v) {
    if (dp[u] != dp[v]) {
      if (dp[u] > dp[v]) swap(u, v);
      v = kth_ancestor(v, dp[v] - dp[u]);
    }
    if (u == v) return u;
    for (int i = __lg(dp[u]); i >= 0; --i) {
      if (dp[u] < (1 << i)) continue;
      if (bl[u][i] != bl[v][i]) u = bl[u][i], v = bl[v][i];
    }
    return bl[u][0];
  }

  // u - v 間のパス上の頂点のうち u から距離 i の頂点
  // (dist(u, v) < i のとき -1)
  int jump(int u, int v, int i) {
    int lc = lca(u, v);
    int d1 = dp[u] - dp[lc];
    if (i <= d1) return kth_ancestor(u, i);
    int d = d1 + dp[v] - dp[lc];
    if (i <= d) return kth_ancestor(v, d - i);
    return -1;
  }
};

template<class T = long long >
struct BIT {
    int n;
    std::vector<T>data;
    BIT():n(0), data(0) {}
    BIT(int N):n(N), data(N) {}
    BIT(vector<T>& N) {
        data = N;
        n = N.size();
    }
    void add(int i,T x){
        assert(i>=0&&i<n);
        i++;
        for(;i<=n;){
            data[i - 1] += x;
            i += (i & -i);
        }
        return;
    }   
    T internal_sum(int r){
        T ret = 0;
        for(;r;){
            ret += data[r - 1];
            r -= (r & -r);
        }
        return ret;
    }
    T sum(int l,int r){
        return internal_sum(r)-internal_sum(l);
    }
};
/**
 * @brief 木に対する一般的なクエリ
 * @docs docs/tree/tree-query.md
 */
#include <utility>
#include <vector>
#include <algorithm>


using Elem=int;
class CsrArray{
public:
    struct ListRange{
        using iterator = typename std::vector<Elem>::iterator;
        iterator begi, endi;
        iterator begin() const { return begi; }
        iterator end() const { return endi; }
        int size() const { return (int)std::distance(begi, endi); }
        Elem& operator[](int i) const { return begi[i]; }
    };
    struct ConstListRange{
        using iterator = typename std::vector<Elem>::const_iterator;
        iterator begi, endi;
        iterator begin() const { return begi; }
        iterator end() const { return endi; }
        int size() const { return (int)std::distance(begi, endi); }
        const Elem& operator[](int i) const { return begi[i]; }
    };
private:
    int m_n;
    std::vector<Elem> m_list;
    std::vector<int> m_pos;
public:
    CsrArray() : m_n(0), m_list(), m_pos() {}
    static CsrArray Construct(int n, std::vector<std::pair<int, Elem>> items){
        CsrArray res;
        res.m_n = n;
        std::vector<int> buf(n+1, 0);
        for(auto& [u,v] : items){ ++buf[u]; }
        for(int i=1; i<=n; i++) buf[i] += buf[i-1];
        res.m_list.resize(buf[n]);
        for(int i=(int)items.size()-1; i>=0; i--){
            res.m_list[--buf[items[i].first]] = std::move(items[i].second);
        }
        res.m_pos = std::move(buf);
        return res;
    }
    static CsrArray FromRaw(std::vector<Elem> list, std::vector<int> pos){
        CsrArray res;
        res.m_n = pos.size() - 1;
        res.m_list = std::move(list);
        res.m_pos = std::move(pos);
        return res;
    }
    ListRange operator[](int u) { return ListRange{ m_list.begin() + m_pos[u], m_list.begin() + m_pos[u+1] }; }
    ConstListRange operator[](int u) const { return ConstListRange{ m_list.begin() + m_pos[u], m_list.begin() + m_pos[u+1] }; }
    int size() const { return m_n; }
    int fullSize() const { return (int)m_list.size(); }
};
// namespace nachia
struct ds{
    static const int B=50;
    static const int B2=B*B;
    array<vc<int>,3>block,pref;
    static const int N=B*B*B;
    vc<pair<int,int>>hist;
    ds(int n){
        assert(n<=B*B*B);
        rep(i,3){
            block[i]=pref[i]=vc<int>(N);
        }
    }
    void add(int i,int x,bool reset=false){
        if(!reset)hist.push_back({i,x});
        rep(t,3){
            block[t][i]+=x;
            bool first=true;
            REP(j,i/B*B,(i/B+1)*B){
                pref[t][j]=block[t][j];
                if(!first){
                    pref[t][j]+=pref[t][j-1];
                }else{
                    first=false;
                }
            }
            i/=B;
        }
    }
    void rollback(){
        auto&[x,y]=hist.back();add(x,-y,1);
        hist.pop_back();
    }
    void reset(){
        for(auto&[x,y]:hist)add(x,-y,1);
        hist.clear();
    }
    //[0,x)
    int sum(int x){
        int res=0;
        rep(t,3){
            res+=x%B?pref[t][x-1]:0;
            x/=B;
        }
        return res;
    }
    int sum(int l,int r){
        return sum(r)-sum(l);
    }
};

CsrArray g;
int id[(int)5e4];
int going[(int)5e4];
int from_leader[250][(int)5e4];
int to_leader[250][(int)5e4];
struct CALC{
    vc<int>vs;
    vc<int>a;
    int n;
    CALC(int n,vc<int>vs):n(n),a(n),vs(vs){}

    void set(int i,int x){
        a[i]=x;
    }
    vvc<ll>calc(){
        rep(i,vs.size())id[vs[i]]=i;
        for(auto&x:vs)going[x]=1;
        vvc<ll>ans(n,vc<ll>(n,-1e9));//i -> j の転倒数
        vvc<ll>over(n,vc<ll>(n,-1e9));//i -> j で a_j より大きいものの個数
        for(auto&x:vs){
            auto dfs=[&](auto&dfs,int u,int p)->void{
                if(p!=-1){
                    over[id[u]][id[x]]=over[id[p]][id[x]]+(a[id[x]]<a[id[u]]);
                }
                for(auto&x:g[u]){
                    if(x==p)continue;
                    if(!going[x])continue;
                    dfs(dfs,x,u);
                }
            };
            over[id[x]][id[x]]=0;
            dfs(dfs,x,-1);
        }
        for(auto&x:vs){
            ans[id[x]][id[x]]=0;
            auto dfs=[&](auto&dfs,int u,int p)->void{
                if(p!=-1){
                    ans[id[x]][id[u]]=over[id[x]][id[u]]+ans[id[x]][id[p]];
                }
                for(auto&x:g[u]){
                    if(x==p)continue;
                    if(!going[x])continue;
                    dfs(dfs,x,u);
                }
            };
            dfs(dfs,x,-1);
        }
        for(auto&x:vs)going[x]=0;
        return ans;
    }
};  
struct Onl{
    int n;
    BIT<int>bit;
    ll inv;
    vc<pair<int,int>>hist;
    Onl(int n):n(n),bit(n),inv(0){}
    void add(int i,int x,bool reset=false){
        if(!reset)hist.push_back({i,x});
        bit.add(i,x);
        inv+=bit.sum(i+1,n)*(reset?-1:1);
    }
    void rollback(){
        auto&[i,x]=hist.back();
        add(i,-x,1);
        hist.pop_back();
    }  
};
struct Onl2{
    int n;
    BIT<int>bit;
    ll inv;
    vc<pair<int,int>>hist;
    Onl2(int n):n(n),bit(n),inv(0){}
    void add(int i,int x,bool reset=false){
        if(!reset)hist.push_back({i,x});
        bit.add(i,x);
        inv+=bit.sum(0,i)*(reset?-1:1);
    }
    void rollback(){
        auto&[i,x]=hist.back();
        add(i,-x,1);
        hist.pop_back();
    }  
};
vc<ll> solve(int n,vc<pair<int,int>>e,vc<int>A,vc<pair<int,int>>Q,bool lock=true){
    for(auto&x:e)x.first--,x.second--;
    for(auto&x:A)x--;
    {
        vc<pair<int,int>>ne=e;for(auto&x:e)ne.push_back({x.second,x.first});
        g=CsrArray::Construct(n,ne);
    }
    vvc<int>G(n);rep(i,n-1)G[e[i].first].push_back(e[i].second),G[e[i].second].push_back(e[i].first);

    Tree tree(G);
    vc<int>leader;//i th leader 
    vc<int>group(n,-1);//leader of vertex i 
    vc<int>sub_id(n,-1);//id in subtree
    vc<int>sub_size;//size of subtree i
    vvc<int>subs;//vertexs of i th subtree
    vc<int>bel_sub(n,-1);//subtree vertex i belong
    vvvc<ll>inv_sub;//inv between same subtree
    vvc<int>sorted_seq(n);//leader to i sorted 
    int SQRT=sqrt(n);
    //get leader inf
    {
        auto push=[&](vc<int>g){
            int gid=leader.size();
            leader.push_back(g[0]);
            for(auto&x:g){
                group[x]=gid;
            }
        };
        vvc<int>res(n);
        auto dfs=[&](auto&dfs,int u,int p)->void{
            auto&tar=res[u];
            res[u].push_back(u);
            for(auto&x:g[u]){
                if(x==p)continue;
                dfs(dfs,x,u);
                for(auto&e:res[x]){
                    tar.push_back(e);
                }
            }
            if(tar.size()>=SQRT){
                push(tar);
                tar={};
            }
            return;
        };  
        dfs(dfs,0,-1);
        auto re=res[0];
        if(re.size())push(re);
    }
    //get subtree inf
    {
        
        for(auto&x:leader){
            for(auto&nx:g[x]){
                if(group[nx]==group[x]){
                    int sid=sub_size.size();
                    int id_insb=0;
                    sub_size.push_back({});
                    subs.push_back({});
                    auto dfs=[&](auto&dfs,int u,int p)->void{
                        sub_size[sid]++;
                        sub_id[u]=id_insb++;
                        bel_sub[u]=sid;
                        subs.back().push_back(u);
                        for(auto&to:g[u]){
                            if(to==p)continue;
                            if(group[to]!=group[u])continue;
                            dfs(dfs,to,u);
                        }
                    };
                    dfs(dfs,nx,x);
                }
            }
        }
    }
    //inv in subtree
    {
        inv_sub.resize(subs.size());
        rep(i,subs.size()){
            CALC calc(subs[i].size(),subs[i]);
            int cnt=0;
            for(auto&x:subs[i]){
                calc.set(sub_id[x],A[x]);
            }
            inv_sub[i]=calc.calc();
        }
    }
    //get all sorted
        auto insert=[&](vc<int>&res,int k){
            rep(i,res.size())if(res[i]>k){
                res.insert(res.begin()+i,k);
                return;
            }
            res.push_back(k);
        };
        auto erase=[&](vc<int>&res,int k){
            rep(i,res.size())if(res[i]==k){
                res.erase(res.begin()+i);
                return;
            }
            assert(0);
        };
        for(auto&x:leader){
            vc<int>res;
            auto dfs=[&](auto&dfs,int u,int p)->void{
                if(u!=x)insert(res,A[u]);
                sorted_seq[u]=res;
                for(auto&to:g[u]){
                    if(to==p)continue;
                    if(group[to]!=group[u])continue;
                    dfs(dfs,to,u);
                }
                if(u!=x)erase(res,A[u]);
            };
            dfs(dfs,x,-1);
        }
    {
        vc<int>alive(n,1);
        vc<int>size(n);
        ds ds(n);
        vc<ll>tmp1(n),tmp2(n);
        Onl onl1(n);
        Onl2 onl2(n);
        auto decomposition=[&](auto&decomposition,int x)->void{
            //find centroid 
            {auto dfs=[&](auto&dfs,int x,int p)->void{
                size[x]=1;
                bool is_c=1;
                for(auto&to:g[x]){
                    if(to==p)continue;
                    if(!alive[to])continue;
                    dfs(dfs,to,x);
                    size[x]+=size[to];
                }
            };
            dfs(dfs,x,-1);}
            int N=size[x];
            int c=-1;
            {
            auto dfs=[&](auto&dfs,int x,int p)->void{
                bool is_c=1;
                for(auto&to:g[x]){
                    if(to==p)continue;
                    if(!alive[to])continue;
                    dfs(dfs,to,x);
                    if(size[to]>N/2)is_c=0;
                }
                if(N-size[x]>N/2)is_c=0;
                if(is_c)c=x;
            };
            dfs(dfs,x,-1);
            }
            //get_inv
            {
                auto dfs=[&](auto&dfs,int u,int p)->void{
                    onl1.add(A[u],1);
                    onl2.add(A[u],1);
                    tmp1[u]=onl1.inv;
                    tmp2[u]=onl2.inv;
                    for(auto&to:g[u]){
                        if(to==p)continue;
                        if(!alive[to])continue;
                        dfs(dfs,to,u);
                    }
                    onl1.rollback();
                    onl2.rollback();
                };
                dfs(dfs,c,-1);
            }
            vc<int>has_leader(g[c].size());
            rep(i,g[c].size()){
                auto dfs=[&](auto&dfs,int u,int p)->bool{
                    if(u==leader[group[u]])return 1;
                    for(auto&to:g[u]){
                        if(to==p)continue;
                        if(!alive[to])continue;
                        if(dfs(dfs,to,u))return 1;
                    }
                    return 0;
                };
                if(alive[g[c][i]])has_leader[i]=dfs(dfs,g[c][i],c);
            }
            vc<int>leader_idx;
            rep(i,g[c].size())if(has_leader[i])leader_idx.push_back(i);
            auto push=[&](int x,int i){
                int true_idx;
                bool f=1;
                int L;
                auto dfs2=[&](auto&dfs2,int u,int p,ll inv1,ll inv2)->void{
                    from_leader[true_idx][u]=(inv1+=ds.sum(A[u]+1,n))+tmp1[u]+tmp2[L];
                    to_leader[true_idx][u]=(inv2+=ds.sum(0,A[u]))+tmp2[u]+tmp1[L];
                    for(auto&to:g[u]){
                        if(to==p)continue;
                        if(!alive[to])continue;
                        dfs2(dfs2,to,u,inv1,inv2);
                    }
                };
                auto dfs1=[&](auto&dfs1,int u,int p)->void{
                    ds.add(A[u],1);
                    if(leader[group[u]]==u){
                        true_idx=group[u];
                        L=leader[true_idx];
                        rep(j,g[c].size()){
                            int to=g[c][j];
                            if(alive[to]&&i!=j)dfs2(dfs2,to,c,0,0);
                        }
                        from_leader[true_idx][c]=tmp2[L];
                        to_leader[true_idx][c]=tmp1[L];
                    }
                    for(auto&to:g[u]){
                        if(to==p)continue;
                        if(!alive[to])continue;
                        dfs1(dfs1,to,u);
                    }
                    ds.rollback();
                    return;
                };
                if(i!=-1)dfs1(dfs1,x,c);
                else true_idx=group[c],L=leader[true_idx],dfs2(dfs2,c,-1,0,0);
            };
            for(auto&i:leader_idx){
                push(g[c][i],i);
            }
            if(leader[group[c]]==c)push(c,-1);

            alive[c]=0;
            for(auto&to:g[c])if(alive[to])decomposition(decomposition,to);
        };
        decomposition(decomposition,0);
    }
    auto merge_sorted=[&](vc<int>&a,vc<int>&b){
        ll inv=0;
        int nb=0;
        for(auto&x:a){
            while(nb!=b.size()&&b[nb]<x)nb++;
            inv+=nb;
        }
        return inv;
    };
    auto merge_sorted2=[&](vc<int>&a,vc<int>&b,vc<int>&c){
        ll inv=0;
        int nb=0;
        int nc=0;
        for(auto&x:a){
            if(nc!=c.size()&&x==c[nc]){
                nc++;
                continue;
            }
            while(nb!=b.size()&&b[nb]<x)nb++;
            inv+=nb;
        }
        return inv;
    };
    auto merge_sorted3=[&](vc<int>&a,vc<int>&b,vc<int>&c){
        ll inv=0;
        int nb=0;
        int nc=0;
        int off=0;
        for(auto&x:a){
            while(nb!=b.size()&&b[nb]<x){
                if(nc!=c.size()&&b[nb]==c[nc]){
                    nc++;
                    off++;
                    continue;
                }
                nb++;
            }
            inv+=nb-off;
        }
        return inv;
    };
    ll ans;
    auto dist=[&](int a,int b){
        return tree.depth(a)+tree.depth(b)-tree.depth(tree.lca(a,b))*2;
    };
    vc<ll>res;
    
    ll off=0;
    rep(i,Q.size()){
        if(lock){
            Q[i].first+=off,Q[i].second+=off;
            Q[i].first%=n,Q[i].second%=n;
        }
        Q[i].first--,Q[i].second--;
        if(Q[i].first<0)Q[i].first+=n;
        if(Q[i].second<0)Q[i].second+=n;
        auto get=[&](int a,int b){
            if(leader[group[a]]==a){
                return from_leader[group[a]][b];
            }
            if(leader[group[b]]==b){
                return to_leader[group[b]][a];
            }
            assert(0);
        };
        auto sol=[&](int a,int b)->ll{
            if(leader[group[a]]==a||leader[group[b]]==b){
                return get(a,b);
            }
            if(group[a]==group[b]){
                if(bel_sub[a]==bel_sub[b]){
                    return inv_sub[bel_sub[a]][sub_id[a]][sub_id[b]];
                }else{
                return get(a,leader[group[a]])+get(leader[group[a]],b)+merge_sorted(sorted_seq[a],sorted_seq[b]);
                }
            }
            int L=tree.lca(a,b);
            if(L==a){
                int L1=tree.nxt(L,leader[group[a]]);
                auto t1=sorted_seq[L1];
                insert(t1,A[leader[group[a]]]);
                return
                +get(leader[group[a]],b)
                -get(leader[group[a]],leader[group[b]])
                -merge_sorted(t1,sorted_seq[b])
                +get(a,leader[group[b]]);
            }
            if(L==b){
                int L1=tree.nxt(b,leader[group[b]]);
                auto t1=sorted_seq[L1];
                insert(t1,A[leader[group[b]]]);
                return
                +get(a,leader[group[b]])
                -get(leader[group[a]],leader[group[b]])
                -merge_sorted(sorted_seq[a],t1)
                +get(leader[group[a]],b);
            }
            auto bet=[&](int a,int b,int c){
                return dist(a,c)+dist(c,b)==dist(a,b);
            };
            if(!bet(a,b,leader[group[a]])){
                int L2=tree.nxt(L,leader[group[a]]);
                auto t1=sorted_seq[L2];
                insert(t1,A[leader[group[a]]]);
                return
                +get(a,leader[group[b]])
                +get(leader[group[a]],b)
                -merge_sorted(t1,sorted_seq[b])
                -get(leader[group[a]],leader[group[b]])
                +merge_sorted2(sorted_seq[a],sorted_seq[b],sorted_seq[L]);
            }
            if(!bet(a,b,leader[group[b]])){
                int L2=tree.nxt(L,leader[group[b]]);
                auto t1=sorted_seq[L2];
                insert(t1,A[leader[group[b]]]);
                return
                +get(a,leader[group[b]])
                +get(leader[group[a]],b)
                -merge_sorted(sorted_seq[a],t1)
                -get(leader[group[a]],leader[group[b]])
                +merge_sorted3(sorted_seq[a],sorted_seq[b],sorted_seq[L]);
            }
            return get(a,leader[group[b]])+get(leader[group[a]],b)-get(leader[group[a]],leader[group[b]])+merge_sorted(sorted_seq[a],sorted_seq[b]);
        };
            off=sol(Q[i].first,Q[i].second);
            res.push_back(off);
        }
        return res;
}   
void sol(){
    int n;
    cin>>n;
    vc<pair<int,int>>e(n-1);
    rep(i,n-1){
        cin>>e[i].first>>e[i].second;
    }
    vc<int>A(n);
    rep(i,n)cin>>A[i];
    int Q;
    cin>>Q;
    vc<pair<int,int>>Query(Q);
    rep(i,Q){
        cin>>Query[i].first>>Query[i].second;
    }
    auto res=solve(n,e,A,Query);
    for(auto&x:res)cout<<x<<endl;
}
int main(){
    cin.tie(0)->sync_with_stdio(0);
    sol();
}
0