• HDU5840(SummerTrainingDay08-B 树链剖分+分块)


    This world need more Zhu

    Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
    Total Submission(s): 454    Accepted Submission(s): 84


    Problem Description

    As we all know, Zhu is the most powerful man. He has the infinite power to protest the world. We need more men like Zhu!

    In Duoladuo, this place is like a tree. There are n vertices and n1 edges. And the root is 1. Each vertex can reached by any other vertices. Each vertex has a people with value Ai named Zhu's believer.

    Liao is a curious baby, he has m questions to ask Zhu. But now Zhu is busy, he wants you to help him answer Liao's questions.

    Liao's question will be like "u v k".

    That means Liao want to know the answer from following code:

      ans = 0; cnt = 0;

      for x in the shortest path from u to v {

        cnt++;
        
        if(cnt mod k == 0) ans = max(ans,a[x]);

      }

      print(ans).

    Please read the hints for more details.
     

    Input

    In the first line contains a single positive integer T, indicating number of test case.

    In the second line there are two numbers nmn is the size of Duoladuo, m is the number of Liao's questions.

    The next line contains n integers A1,A2,...An, means the value of ith vertex.

    In the next n1 line contains tow numbers uv. It means there is an edge between vertex u and vertex v.

    The next m lines will be the Liao's question: 

    u v k

    1T10,1n100000,1m100000,1u,vn,1k, Ai1000000000.
     

    Output

    For each case, output Case #i: (i is the number of the test case, from 1 to T). 

    Then, you need to output the answer for every Liao's questions.
     

    Sample Input

    1 5 5 1 2 4 1 2 1 2 2 3 3 4 4 5 1 1 1 1 3 2 1 3 100 1 5 2 1 3 1
     

    Sample Output

    Case #1: 1 2 0 2 4

    Hint

    In query 1,there are only one vertex in the path,so the answer is 1. In query 2,there are three vertices in the path.But only the vertex 2 mod 2 equals to 0. In query 3,there are three vertices in the path.But no vertices mod 100 equal to 0. In query 4,there are five vertices in the path.There are two vertices mod 2 equal to 0.So the answer is max(a[2],a[4]) = 2. In query 5,there are three vertices in the path.And all the vertices mod 1 equal to 0. So the answer is a[3] = 4.
     

    Author

    UESTC
     

    Source

     
      1 //2017-08-08
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <iostream>
      5 #include <algorithm>
      6 #include <vector>
      7 #define lson (id<<1)
      8 #define rson ((id<<1)|1)
      9 
     10 using namespace std;
     11 
     12 const int N = 100010;
     13 const int LEN = 20;//块的大小
     14 vector<int> G[N];
     15 int n, m, label, answer[N];
     16 
     17 //树链剖分
     18 int arr[N];//arr[i]表示节点i的权值
     19 int fa[N];//fa[i]表示节点i的父亲
     20 int son[N];//son[i]表示节点i的重儿子
     21 int top[N];//top[i]表示节点i所在重链的顶端节点
     22 int size[N];//size[i]表示以节点i为根的子树的节点数
     23 int deep[N];//deep[i]表示节点i的深度
     24 int postion[N];//postion[i]表示节点i在线段树中的位置
     25 int trID[N];//trID[i]表示节点i在剖分后的新编号
     26 
     27 void dfs1(int u, int father){
     28     fa[u] = father;
     29     son[u] = 0;
     30     size[u] = 1;
     31     for(auto v: G[u]){
     32         if(v == father)continue;
     33         deep[v] = deep[u]+1;
     34         dfs1(v, u);
     35         size[u] += size[v];
     36         if(size[v] > size[son[u]])
     37             son[u] = v;
     38     }
     39 }
     40 
     41 void dfs2(int u, int ancestor){
     42     top[u] = ancestor;
     43     postion[u] = ++label;
     44     trID[label] = u;
     45     if(son[u])
     46         dfs2(son[u], ancestor);
     47     for(auto v: G[u]){
     48         if(v == fa[u] || v == son[u])
     49             continue;
     50         dfs2(v, v);
     51     }
     52 }
     53 
     54 //最近公共祖先
     55 inline int lca(int u, int v){
     56     while(top[u] ^ top[v]){
     57         if(deep[top[u]] < deep[top[v]])
     58             swap(u, v);
     59         u = fa[top[u]];
     60     }
     61     return deep[u] < deep[v] ? u : v;
     62 }
     63 
     64 //线段树
     65 struct Node{
     66     int l, r, v;
     67 }tree[N<<2];
     68 int nS[N], qL[N], qR[N];
     69 
     70 void build(int id, int l , int r){
     71     tree[id].l = l;
     72     tree[id].r = r;
     73     if(l == r){
     74         tree[id].v = arr[trID[nS[l]]];
     75         return;
     76     }
     77     int mid = (l+r)>>1;
     78     build(lson, l, mid);
     79     build(rson, mid+1, r);
     80     tree[id].v = max(tree[lson].v, tree[rson].v);
     81 }
     82 
     83 int query(int id, int l, int r){
     84     if(tree[id].l == l && tree[id].r == r)
     85         return tree[id].v;
     86     int mid = (tree[id].l+tree[id].r)>>1;
     87     if(l > mid)return query(rson, l, r);
     88     if(r <= mid)return query(lson, l, r);
     89     return max(query(lson, l, mid), query(rson, mid+1, r));
     90 }
     91 
     92 inline int cal(int l, int r, int k){
     93     if(qL[k] > qR[k])return 0;
     94     l = lower_bound(nS+qL[k], nS+qR[k]+1, l)-nS;
     95     r = upper_bound(nS+qL[k], nS+qR[k]+1, r)-nS-1;
     96     if(l <= r)return query(1, l, r);
     97     else return 0;
     98 }
     99 
    100 int question(int u, int v, int k){
    101     int ans = -1, f = lca(u, v);
    102     int uk = (deep[u] + 1)%k;
    103     int vk = (deep[f] + (k - (deep[u]-deep[f]+1)%k)) % k;
    104     while(top[u] ^ top[v]){
    105         if(deep[top[u]] > deep[top[v]]){
    106             ans = max(ans, cal(postion[top[u]], postion[u], uk));
    107             u = fa[top[u]];
    108         }else{
    109             ans = max(ans, cal(postion[top[v]], postion[v], vk));
    110             v = fa[top[v]];
    111         }
    112     }
    113     if(deep[u] > deep[v])
    114         ans = max(ans, cal(postion[v], postion[u], uk));
    115     else 
    116         ans = max(ans, cal(postion[u], postion[v], vk));
    117     return ans;
    118 }
    119 
    120 vector<int> block[LEN];
    121 vector< pair< pair<int, int>, int > > qs[LEN+5];
    122 vector< pair< pair<int, int>, pair<int, int> > > qy[N];
    123 void solve(int k){
    124     for(int i = 1; i <= n; i++){
    125         int u = trID[i];
    126         block[deep[u]%k].push_back(u);
    127     }
    128     label = 0;
    129     for(int i = 0; i < k; i++){
    130         qL[i] = label + 1;
    131         for(auto x: block[i])
    132             nS[++label] = postion[x];
    133         qR[i] = label;
    134     }
    135     build(1, 1, n);
    136     for(auto &x: qs[k])
    137         answer[x.second] = question(x.first.first, x.first.second, k);
    138     for(int i = 0; i < k; i++)
    139         block[i].clear();
    140     qs[k].clear();
    141 }
    142 
    143 int sk[N], tp;//sk为栈, tp为栈顶指针
    144 
    145 void dfs(int u){
    146     sk[++tp] = u;
    147     for(auto &x: qy[u]){
    148         for(int i = tp-x.first.second;
    149             i > 0 && deep[sk[i]] >= deep[x.first.first];
    150             i -= x.second.first)
    151             answer[x.second.second] = max(answer[x.second.second], arr[sk[i]]);
    152     }
    153     qy[u].clear();
    154     for(auto v : G[u]){
    155         if(v ^ fa[u])
    156             dfs(v);
    157     }
    158     --tp;
    159 }
    160 
    161 int main()
    162 {
    163     //freopen("dataB.txt", "r", stdin);
    164     int T, kase = 0;
    165     scanf("%d", &T);
    166     while(T--){
    167         scanf("%d%d", &n, &m);
    168         for(int i = 1; i <= n; i++)
    169               scanf("%d", &arr[i]);
    170         int u, v, k;
    171         for(int i = 1; i <= n; i++)
    172             G[i].clear();
    173         for(int i = 1; i <= n-1; i++){
    174               scanf("%d%d", &u, &v);
    175             G[u].push_back(v);
    176             G[v].push_back(u);
    177         }
    178         label = 0;
    179         dfs1(1, 1);
    180         dfs2(1, 1);
    181         //debug();
    182         for(int i = 0; i < m; i++){
    183             scanf("%d%d%d", &u, &v, &k);
    184             if(k >= LEN){
    185                 int f = lca(u, v);
    186                 int d = (deep[u]+deep[v]-2*deep[f]+1)%k;
    187                 if(u ^ f)
    188                     qy[u].push_back({ {f, k-1}, {k, i} });
    189                 if(v ^ f)
    190                     qy[v].push_back({ {f, d}, {k, i} });
    191             }else{
    192                 qs[k].push_back({ {u, v}, i });
    193             }
    194         }
    195         memset(answer, 0, sizeof(answer));
    196         for(int i = 1; i < LEN; i++)
    197             if(qs[i].size())
    198                 solve(i);
    199         tp = 0;
    200         dfs(1);
    201         printf("Case #%d:
    ", ++kase);
    202         for(int i = 0; i < m; i++)
    203             printf("%d
    ", answer[i]);
    204     }
    205 
    206     return 0;
    207 }
  • 相关阅读:
    为什么游戏行业喜欢用PolarDB
    以“升舱”之名,谈谈云原生数据仓库AnalyticDB的核心技术
    研发效能的思考总结
    InnoDB之UNDO LOG介绍
    数据库事务隔离发展历史
    拥抱开放,Serverless 时代的下一征程
    对软件系统的一些理解
    【20220221】数据得多维去看
    【20220222】充满爱,必然以被爱作为回报
    【一句日历】2022年3月
  • 原文地址:https://www.cnblogs.com/Penn000/p/7309298.html
Copyright © 2020-2023  润新知