4000 【SJTUOJ笔记】P1118 Travel
2018-03-29 16:06
344 查看
https://acm.sjtu.edu.cn/OnlineJudge/problem/1118
由于题目含有大量的合并和查询操作,很容易想到用并查集来做。关键在于,如何在合并集合的同时维护题目要求的信息。
并查集的特点是,任何操作都可以变化为对集合根的操作。但反过来,却无法把根的状态改变直接反映到下面的每个集合元素中。在本题中,具体体现就是一堆旅行团会被根带着一起旅行,但无法在近似O(1)O(1)的时间修改每个旅行团已经走过的城市个数。因此,这里采用了类似于线段树中lazy标记的思想,先记录根结点带着下面的旅行团走过了几个城市,合并时再下推标记,把O(n)O(n)的下推操作的次数尽可能减少。
具体如下:
由于题目含有大量的合并和查询操作,很容易想到用并查集来做。关键在于,如何在合并集合的同时维护题目要求的信息。
并查集的特点是,任何操作都可以变化为对集合根的操作。但反过来,却无法把根的状态改变直接反映到下面的每个集合元素中。在本题中,具体体现就是一堆旅行团会被根带着一起旅行,但无法在近似O(1)O(1)的时间修改每个旅行团已经走过的城市个数。因此,这里采用了类似于线段树中lazy标记的思想,先记录根结点带着下面的旅行团走过了几个城市,合并时再下推标记,把O(n)O(n)的下推操作的次数尽可能减少。
具体如下:
void merge(int x, int y){ int p = find(x), q = find(y); sum[q] += sum[p]; //sum[k]记录k号原始旅行团所在的大旅行团包含多少原始旅行团 for (int i = 1; i <= n; ++i){ //下推标记 int t = find(i); if (t == p || t == q) trl[i] += ex[t]; //ex[k]记录k号原始旅行团所在的大旅行团在合并前走过了多少城市 } ex[p] = ex[q] = 0; parent[p] = q; }
case 'T': cin >> x >> y; p = find(x); q = find(y); //找到x和y的根 if (p != q){ a = nowat[p]; //nowat[k]记录k号原始旅行团在哪个城市 b = nowat[q]; now[a] = -1; //now[k]记录k号城市的大旅行团根的编号,-1表示没有旅行团在k号城市 nowat[p] = b; ++ex[p]; //加标记 merge(y, x); } break; case 'Q': cin >> x; p = find(x); cout << nowat[p] << ' ' << sum[p] << ' ' << trl[x] + ex[p] << '\n'; //trl[k]记录k号原始旅行团走过了几个城市 break;
相关文章推荐
- MFC中消息笔记 4000
- 天融信防火墙NGFW4000-UF防火墙启用PPTP笔记
- Programming With Microsoft Visual Studio C++.NET 6th Edition 读书 4000 笔记(1) Chapter 5: Windows Message Mapping
- 4000 Numpy高级学习笔记
- 4000 JAVA笔记-Scanner中next()与nextLine()
- 【SJTUOJ笔记】P1092 小F的地板
- 3. Longest Substring Without Repeating Characters --- leetco 4000 de算法笔记
- opencv 4000 学习笔记-线性空间滤波
- 4000 【数据结构笔记】归并排序(merge_sort)-- python2.7
- 4000 httpbin 学习笔记.
- 【SJTUOJ笔记】P1012 增长率问题
- POJ 1310 Nonstop Travel 笔记
- MAVEN入门指南——学习笔记 4000
- 4000 <机器学习笔记-05 ><scikit-learn 05>决策树 & 随机森林
- Gvim开发环境配置笔记--Win 4000 dows篇
- Java 数组排序( 4000 冒泡和选择排序) 学习笔记
- 【SJTUOJ笔记】P1122 二哥开房间
- 4000 常见布局管理器笔记小结
- Spring学习笔记之Spring MVC的高级技术 4000
- 【SJTUOJ笔记】P1055 二哥切巧克力