【hihoCoder第十五周】最近公共祖先·二

老实说我没有读题,看见标题直接就写了,毕竟hiho上面都是裸的算法演练。

大概看了下输入输出,套着bin神的模板,做了个正反map映射,但是怎么都得不了满分。等这周结束后,找高人询问下trick。

若是有人找出了错误,或是发现代码中的不足,求指出。感激!~

以下是个人80分的代码。

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3
  4 const int MAXN = 1000010;
  5 int rmq[2 * MAXN]; //rmq数组,就是欧拉序列对应的深度序列
  6
  7 struct ST {
  8     int mm[2 * MAXN];
  9     int dp[2 * MAXN][20]; //最小值对应的下标
 10     void init(int n) {
 11         mm[0] = -1;
 12         for(int i = 1; i <= n; i++) {
 13             mm[i] = ((i & (i - 1)) == 0) ? mm[i - 1] + 1 : mm[i - 1];
 14             dp[i][0] = i;
 15         }
 16         for(int j = 1; j <= mm[n]; j++)
 17             for(int i = 1; i + (1 << j) - 1 <= n; i++)
 18                 dp[i][j] = rmq[dp[i][j - 1]] <
 19                            rmq[dp[i + (1 << (j - 1))][j - 1]] ? dp[i][j - 1] : dp[i + (1 << (j - 1))][j - 1];
 20     }
 21     int query(int a, int b) { //查询[a,b]之间最小值的下标
 22         if(a > b)swap(a, b);
 23         int k = mm[b - a + 1];
 24         return rmq[dp[a][k]] <=
 25                rmq[dp[b - (1 << k) + 1][k]] ? dp[a][k] : dp[b - (1 << k) + 1][k];
 26     }
 27 };
 28 //边的结构体定义
 29 struct Edge {
 30     int to, next;
 31 };
 32
 33 Edge edge[MAXN * 2];
 34
 35 int tot, head[MAXN];
 36 int F[MAXN * 2]; //欧拉序列,就是dfs遍历的顺序,长度为2*n-1,下标从1开始
 37 int P[MAXN];//P[i]表示点i在F中第一次出现的位置
 38 int cnt;
 39 ST st;
 40 map<string, int> Hash_zh;
 41 map<int, string> Hash_fa;
 42
 43 void init() {
 44     tot = 0;
 45     memset(head, -1, sizeof(head));
 46     Hash_zh.clear();
 47     Hash_fa.clear();
 48 }
 49
 50 void addedge(int u, int v) { //加边,无向边需要加两次
 51     edge[tot].to = v;
 52     edge[tot].next = head[u];
 53     head[u] = tot++;
 54 }
 55
 56 void dfs(int u, int pre, int dep) {
 57     F[++cnt] = u;
 58     rmq[cnt] = dep;
 59     P[u] = cnt;
 60     for(int i = head[u]; i != -1; i = edge[i].next) {
 61         int v = edge[i].to;
 62         if(v == pre)continue;
 63         dfs(v, u, dep + 1);
 64         F[++cnt] = u;
 65         rmq[cnt] = dep;
 66     }
 67 }
 68 void LCA_init(int root, int node_num) { //查询LCA前的初始化
 69     cnt = 0;
 70     dfs(root, root, 0);
 71     st.init(2 * node_num - 1);
 72 }
 73
 74 int query_lca(int u, int v) { //查询u,v的lca编号
 75     return F[st.query(P[u], P[v])];
 76 }
 77
 78 bool flag[MAXN];
 79
 80 int main() {
 81     int T, N;
 82     int u, v, cnt;
 83     string str_u, str_v;
 84     while(~scanf("%d", &N)) {
 85         init();
 86         cnt = 1;
 87         memset(flag, false, sizeof(flag));
 88         for(int i = 1; i <= N; i++) {
 89             //scanf("%d%d", &u, &v);
 90             cin >> str_u >> str_v;
 91             if (Hash_zh[str_u] == 0) {
 92                 Hash_fa[cnt] = str_u;
 93                 Hash_zh[str_u] = cnt ++;
 94             }
 95             if (Hash_zh[str_v] == 0) {
 96                 Hash_fa[cnt] = str_v;
 97                 Hash_zh[str_v] = cnt ++;
 98             }
 99             u = Hash_zh[str_u];
100             v = Hash_zh[str_v];
101             addedge(u, v);
102             addedge(v, u);
103             flag[v] = true;
104         }
105         int root;
106         for(int i = 1; i <= N; i++) {
107             if(!flag[i]) {
108                 root = i;
109                 break;
110             }
111         }
112         LCA_init(root, N);
113         int query_n;
114         scanf ("%d", &query_n);
115         for (int i = 1; i <= query_n; ++ i) {
116             //scanf("%d%d", &u, &v);
117             cin >> str_u >> str_v;
118
119             if (str_u == str_v) {
120                 cout << str_u << endl;
121                 continue;
122             }
123
124             u = Hash_zh[str_u];
125             v = Hash_zh[str_v];
126             cout << Hash_fa[query_lca(u, v)] << endl;
127         }
128     }
129     return 0;
130 }
时间: 2024-10-10 15:03:41

【hihoCoder第十五周】最近公共祖先·二的相关文章

hiho一下 第十五周——最近公共祖先&#183;二(Trajan,离线LCA)

题目连接 http://hihocoder.com/problemset/problem/1067 题目大意 就是一棵树求任意两个节点的最近公共祖先. 算法描述 在题目的提示里面有比较详细的解释.这里就不多说了.这种算法的时间复杂度是O(n+q). 在算法的实现上也有一些技巧,在参考了一些代码后写了一个比较精简的Trajan_LAC算法. #include <bits/stdc++.h> using namespace std; typedef long long LL; const int

hihocoder 第二十五周 spfa 最短路

其实hihocoder里的题目目前大都是模板题啊-.- 这周的是SPFA,暑假的时候有看过SPFA,不过一直用的都是Dijkstra,感觉spfa要更加简洁一点~~,今天找了一份之前一直都看不太懂所以就没怎么用的模板==,今天耐下心来观摩最终还是看懂了hh. ============================================================ 所以以后都用spfa吧~~~速度快&&避开了stl~~,写这个bolg主要是拿来记录模板的 #include &

每周进度条(第十五周)

第十五周进度条   第十五周 所花时间 1h 代码量(行)  100 博客量(篇)  1 学到的知识 对图片的处理 在Android程序中加入图片

每周进度表(第十五周)

  第十五周 所花时间(包括上课) 5(小时) 代码量(行) 200 博客量(篇) 7 了解到的知识点 如何对界面进行美化 如何处理anroid里的图片

学习进度条(十五周)

本周主要是对于团队开发项目的修改完善.   第十五周 所花时间(包括上课) 上课2小时,课后10小时 代码量(行) 200+ 博客量 2 了解到的知识点 服务器连接GET方法

学习进度条--第十五周

  第十五周 所花时间(包括上课时间) 4小时(包括上课2小时) 代码量(行) 70 博客量(篇) 1篇 了解到的知识点 软件的开发文档具有重要作用,书面计划是精确和可以沟通的. 软件开发中应及时解决遇到问题,不然容易造成不可挽回的错误.

第十五周周总结

周数 专业学习目标 专业学习时间 新增代码量 人文方面的学习 知识技能总结 第 十 五 周 数据结构:学习与排序有关的知识 4h 300左右 练习与排序有关的习题 计算机网络:继续练习网络服务器的搭建 3h 300左右 继续练习网络服务器的搭建 WEB:继续学习个人主页相关知识点 3h 300左右 练习个人主页相关知识点

第十五周进度条

第十五周          日期  星期一   星期二   星期三   星期四   星期五   星期六   星期日  了解到的知识点   分页分为真分页和加分页:假分页是先将所需要的数据全部查询出来(坏处是第一次很慢好处是点击下一页会很快)真分页是只查询需要的那几条(比如select * from table limit(0,5))(每次运行时间一样) jsp进入页面鼠标落到指定文本框 function setfocus(){   UserName.focus();} <body ><i

信息安全系统设计基础第十五周总结

信息安全系统设计基础第十五周总结 [内容:链接汇总] 一.每周读书笔记链接汇总 [第一周读书笔记] http://www.cnblogs.com/shadow135211/p/4824555.html [第二周读书笔记] http://www.cnblogs.com/shadow135211/p/4842258.html [第三周读书笔记] http://www.cnblogs.com/shadow135211/p/4854920.html [第四周读书笔记] (读书笔记从“第一周”开始命名,为