zoukankan      html  css  js  c++  java
  • 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
    ", query(1, n, 1, ua, ub));
    136         }
    137     }
    138     return 0;
    139 }
  • 相关阅读:
    Intersecting Lines (计算几何基础+判断两直线的位置关系)
    Morley's Theorem (计算几何基础+向量点积、叉积、旋转、夹角等+两直线的交点)
    TOYS(计算几何基础+点与直线的位置关系)
    Berland National Library
    PAT L2-017. 人以群分
    6.9服务与主机之间的映射
    第六章 部署
    5.12.1再试一次
    第5章 分解单块系统
    4.14.6 —种混合方式
  • 原文地址:https://www.cnblogs.com/oneshot/p/4561916.html
Copyright © 2011-2022 走看看