HDU5266---pog loves szh III (线段树+LCA)

 

题意:N个点的有向树, Q次询问, 每次询问区间[L, R]内所有点的LCA。

大致做法:线段树每个点保存它的孩子的LCA值, 对于每一次询问只需要 在线段树查询即可。

  1 #include <bits/stdc++.h>

  2 using namespace std;

  3 const int MAXN = 3e5+10;

  4 struct Edge{

  5     int to, next;

  6 }e[MAXN << 1];

  7 int head[MAXN], tot_edge;

  8 void Add_Edge (int x, int y){

  9     e[tot_edge].to = y;

 10     e[tot_edge].next = head[x];

 11     head[x] = tot_edge++;

 12 }

 13 int n, q, MAX_LOG_V;

 14 bool vis[MAXN];

 15 void init (){

 16     MAX_LOG_V = 20;

 17     tot_edge = 0;

 18     memset(head, -1, sizeof (head));

 19     memset(vis, false, sizeof (vis));

 20 }

 21 int dep[MAXN], pa[25][MAXN];

 22 void DFS (int r, int pre, int d){                    // DFS 或 BFS都可以, G++下BFS

 23     dep[r] = d;

 24     pa[0][r] = pre;

 25     for (int i = head[r]; ~i; i = e[i].next){

 26         int u = e[i].to;

 27         if (pre != u){

 28             DFS(u, r, d+1);

 29         }

 30     }

 31 }

 32 void BFS (int r, int pre, int d){

 33     dep[r] = d;

 34     pa[0][r] = pre;

 35     queue <int>Q;

 36     Q.push(r);

 37     vis[r] = true;

 38     while (!Q.empty()){

 39         int u = Q.front();

 40         Q.pop();

 41         for (int i = head[u]; ~i; i = e[i].next){

 42             int v = e[i].to;

 43             if (!vis[v]){

 44                 dep[v] = dep[u] + 1;

 45                 pa[0][v] = u;

 46                 Q.push(v);

 47                 vis[v] = true;

 48             }

 49         }

 50     }

 51 }

 52 void pre_solve (){

 53     BFS(1, -1, 0);

 54     for (int k = 0; k + 1 < MAX_LOG_V; k++){

 55         for (int v = 1; v <= n; v++){

 56             if (pa[k][v] < 0){

 57                 pa[k+1][v] = -1;

 58             }else{

 59                 pa[k+1][v] = pa[k][pa[k][v]];

 60             }

 61         }

 62     }

 63 }

 64 int LCA (int u, int v){

 65     if (dep[u] > dep[v]){

 66         swap(u, v);

 67     }

 68     for (int k = 0; k < MAX_LOG_V; k++){

 69         if ((dep[v] - dep[u]) >> k & 1){

 70             v = pa[k][v];

 71         }

 72     }

 73     if (u == v){

 74         return u;

 75     }

 76     for (int k = MAX_LOG_V-1; k >= 0; k--){

 77         if (pa[k][u] != pa[k][v]){

 78             u = pa[k][u];

 79             v = pa[k][v];

 80         }

 81     }

 82     return pa[0][u];

 83 }

 84 int seg[MAXN << 2];

 85 void push_up(int pos){

 86     seg[pos] = LCA(seg[pos<<1], seg[pos<<1|1]);

 87 }

 88 void build (int l, int r, int pos){

 89     if (l == r){

 90         seg[pos] = l;

 91         return ;

 92     }

 93     int mid = (l + r) >> 1;

 94     build(l, mid, pos<<1);

 95     build(mid+1, r, pos<<1|1);

 96     push_up(pos);

 97 }

 98 int query (int l, int r, int pos, int ua, int ub){

 99     if (ua <= l && ub >= r){

100         return seg[pos];

101     }

102     int mid = (l + r) >> 1;

103     int t1 = -1, t2 = -1;

104     if (ua <= mid){

105         t1 = query(l, mid, pos<<1, ua, ub);

106     }

107     if (ub > mid){

108         t2 = query(mid+1, r, pos<<1|1, ua, ub);

109     }

110     if (t1 == -1 || t2 == -1){

111         return max(t1, t2);

112     }else{

113         return LCA(t1, t2);

114     }

115 }

116 int main()

117 {

118     #ifndef ONLINE_JUDGE

119         freopen("in.txt","r",stdin);

120     #endif

121     while (~ scanf ("%d", &n)){

122         init();

123         for (int i = 0; i < n-1; i++){

124             int u, v;

125             scanf ("%d%d", &u, &v);

126             Add_Edge(u, v);

127             Add_Edge(v, u);

128         }

129         pre_solve();

130         build(1, n, 1);

131         scanf ("%d", &q);

132         for (int i = 0; i < q; i++){

133             int ua, ub;

134             scanf ("%d%d", &ua, &ub);

135             printf("%d\n", query(1, n, 1, ua, ub));

136         }

137     }

138     return 0;

139 }

 

你可能感兴趣的:(love)