建模简析:

  1. /*
  2. HDU 6039 - Gear Up [ 建模,线段树,图论 ] | 2017 Multi-University Training Contest 1
  3. 题意:
  4. 给你n个齿轮,有些齿轮是同轴的(角速度相同),有些是同边的(线速度相同),任意两个齿轮两种关系中至多只有一种,且任意两个齿轮之间只有一条路径
  5. 给出所有齿轮的半径和 m组两两之间的关系
  6. 两种操作:1. 把改变某个齿轮的半径; 2. 赋予某个齿轮一个角速度,问所有齿轮中最大的角速度是多少
  7. 分析:
  8. 相邻齿轮连边建图,原图是森林,按单棵树考虑。
  9. 由于同轴的齿轮在角速度上相同,故可缩点成齿轮组,新图上各组齿轮同边,且任意两个齿轮组只有一对齿轮同边
  10. 单棵树上的齿轮在角速度上有着倍数关系,故可以以某一个齿轮为参照,维护别的齿轮和它在角速度上的倍数
  11. 可以想象,以根节点为参照,齿轮组 u 对于根节点的角速度的倍数与其直接相邻的齿轮 f 的关系 Ku = Kf * Rf / Ru
  12. 当某个齿轮半径改变后,相当于区间修改子树的倍数,查询则是查询该齿轮所在树的最大值
  13. 大体看得出线段树模型,根据dfs序维护,但是乘法不易维护,则将上表达式取对数:log2(Ku) = log2(Kf) + log2(Rf) - log2(Ru)
  14. 维护对数则只需维护加减法,由于题中半径均为2的幂次,故对数取以二为底
  15.  
  16. 查询操作容易写,修改操作需分类讨论
  17. 1.该齿轮是直接与上一个齿轮组同边的齿轮
  18. 该齿轮变大,同轴所有齿轮角速度变慢,与该齿轮直接同边的子树上的齿轮组不受影响,反之亦然
  19. 2.该齿轮不是直接与上一个齿轮组同边的齿轮
  20. 该齿轮变大,同轴所有齿轮角速度不受影响,与该齿轮直接同边的子树上的齿轮组变快,反之亦然
  21.  
  22. 具体操作时,维护两个dfs序,一个是同轴齿轮组的整棵子树的dfs序,另一个是与该齿轮直接同边的子树dfs序
  23. 维护后一个dfs序时,可对于每一个节点,把这个节点所有连接的点排序,使得和该点同边的点在对应 vector 中的前缀里(就不用缩点了)
  24.  
  25. 编码时长:8小时(-INF)
  26. */
  27. #include <bits/stdc++.h>
  28. using namespace std;
  29. const int N = 100005;
  30. const int INF = 0x3f3f3f3f;
  31. double ln2 = log(2.);
  32. struct Edge{
  33. int v, type;
  34. };
  35. bool cmp(Edge a, Edge b) {
  36. return a.type > b.type;
  37. }
  38. vector<Edge> edge[N];
  39. int rad[N], rate[N], f[N], rt[N];
  40. int l[N], r[N], ll[N], rr[N], pos, p[N];
  41. int n, m, q;
  42. void init(){
  43. for (int i = 0; i < N; i++) {
  44. edge[i].clear();
  45. ll[i] = INF;
  46. l[i] = r[i] = rr[i] = 0;
  47. f[i] = 0;
  48. }
  49. pos = 0;
  50. }
  51. void dfs(int u, int pre)
  52. {
  53. sort(edge[u].begin(), edge[u].end(), cmp);
  54. rt[u] = rt[pre];
  55. l[u] = ++pos;
  56. p[pos] = u;
  57. for (const auto& e : edge[u])
  58. {
  59. if (e.v == pre) continue;
  60. if (e.type == 1) {
  61. rate[e.v] = rad[u] - rad[e.v] + rate[u];
  62. f[e.v] = e.v;
  63. ll[u] = min(ll[u], pos+1);
  64. dfs(e.v, u);
  65. rr[u] = max(rr[u], pos);
  66. } else {
  67. rate[e.v] = rate[u];
  68. f[e.v] = f[u];
  69. dfs(e.v, u);
  70. }
  71. }
  72. r[u] = pos;
  73. }
  74. int Max[N<<2], add[N<<2];
  75. void Up(int x) {
  76. Max[x] = max(Max[x<<1], Max[x<<1|1]);
  77. }
  78. void Down(int x) {
  79. if (add[x]) {
  80. Max[x<<1] += add[x];
  81. Max[x<<1|1] += add[x];
  82. add[x<<1] += add[x];
  83. add[x<<1|1] += add[x];
  84. add[x] = 0;
  85. }
  86. }
  87. void Build(int l, int r, int x) {
  88. add[x] = 0;
  89. if (l == r) {
  90. Max[x] = rate[p[l]]; return;
  91. }
  92. int mid = (l+r) >> 1;
  93. Build(l, mid, x<<1); Build(mid+1, r, x<<1|1);
  94. Up(x);
  95. }
  96. void Change(int L, int R, int num, int l, int r, int x) {
  97. if (L <= l && r <= R) {
  98. add[x] += num; Max[x] += num;
  99. return;
  100. }
  101. Down(x);
  102. int mid = (l + r) >> 1;
  103. if (L <= mid) Change(L, R, num, l, mid, x<<1);
  104. if (mid < R) Change(L, R, num, mid+1, r, x<<1|1);
  105. Up(x);
  106. }
  107. int Query(int L, int R, int l, int r, int x) {
  108. if (L <= l && r <= R) return Max[x];
  109. Down(x);
  110. int mid = (l+r) >> 1;
  111. int res = -INF;
  112. if (L <= mid) res = max(res, Query(L, R, l, mid, x<<1));
  113. if (R > mid) res = max(res, Query(L, R, mid+1, r, x<<1|1));
  114. return res;
  115. }
  116. int main()
  117. {
  118. int tt = 0, i, a, x, y;
  119. while (~scanf("%d%d%d", &n, &m, &q))
  120. {
  121. init();
  122. for (i = 1; i <= n; i++)
  123. {
  124. scanf("%d", &rad[i]);
  125. rad[i] = log2(rad[i]);
  126. }
  127. for (i = 1; i <= m; i++)
  128. {
  129. scanf("%d%d%d", &a, &x, &y);
  130. edge[x].push_back(Edge{y, a});
  131. edge[y].push_back(Edge{x, a});
  132. }
  133. for (i = 1; i <= n; i++)
  134. if (!f[i]) {
  135. rt[i] = f[i] = i;
  136. rate[i] = 0;
  137. dfs(i, i);
  138. }
  139. Build(1, n, 1);
  140. printf("Case #%d:\n", ++tt);
  141. while (q--)
  142. {
  143. scanf("%d%d%d", &a, &x, &y);
  144. if (a == 1)
  145. {
  146. y = log2(y);
  147. if (f[x] == x && rt[x] != x) Change(l[x], r[x], rad[x]-y, 1, n, 1);
  148. if (ll[x] <= rr[x]) Change(ll[x], rr[x], y-rad[x], 1, n, 1);
  149. rad[x] = y;
  150. }
  151. else
  152. {
  153. int km = Query(l[rt[x]], r[rt[x]], 1, n, 1);
  154. int k = Query(l[x], l[x], 1, n, 1);
  155. double au = log2(y) + km - k;
  156. printf("%.3f\n", au*ln2);
  157. }
  158. }
  159. }
  160. }

  

按标程的思路,不同的主要是缩点:

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int N = 100005;
  4. const int INF = 0x3f3f3f3f;
  5. double ln2 = log(2.);
  6. int f[N];
  7. int sf(int x) {
  8. return x == f[x] ? x : f[x] = sf(f[x]);
  9. }
  10. struct Edge{ int v, w, dis; };
  11. vector<int> edge[N];
  12. vector<Edge> lnk[N];
  13. int rad[N], rt[N], rate[N], up[N];
  14. int l[N], r[N], ll[N], rr[N], pos;
  15. int n, m, q;
  16. void init()
  17. {
  18. for (int i = 0; i < N; i++)
  19. {
  20. f[i] = i;
  21. edge[i].clear();
  22. lnk[i].clear();
  23. l[i] = r[i] = 0;
  24. ll[i] = INF;
  25. rt[i] = up[i]= rr[i] = 0;
  26. }
  27. pos = 0;
  28. }
  29. void dfs(int u, int pre, int root, int dis)
  30. {
  31. rt[u] = root;
  32. l[u] = ++pos;
  33. rate[l[u]] = dis;
  34. for (const auto &e: lnk[u])
  35. {
  36. if (pre == e.v) {
  37. up[e.w] = 1;
  38. } else {
  39. ll[e.w] = min(ll[e.w], pos+1);
  40. dfs(e.v, u, root, dis+e.dis);
  41. rr[e.w] = max(rr[e.w], pos);
  42. }
  43. }
  44. r[u] = pos;
  45. }
  46. int Max[N<<2], add[N<<2];
  47. void Up(int x) {
  48. Max[x] = max(Max[x<<1], Max[x<<1|1]);
  49. }
  50. void Down(int x) {
  51. if (add[x]) {
  52. Max[x<<1] += add[x];
  53. Max[x<<1|1] += add[x];
  54. add[x<<1] += add[x];
  55. add[x<<1|1] += add[x];
  56. add[x] = 0;
  57. }
  58. }
  59. void Build(int l, int r, int x) {
  60. add[x] = 0;
  61. if (l == r) {
  62. Max[x] = rate[l]; return;
  63. }
  64. int mid = (l+r) >> 1;
  65. Build(l, mid, x<<1); Build(mid+1, r, x<<1|1);
  66. Up(x);
  67. }
  68. void Change(int L, int R, int num, int l, int r, int x) {
  69. if (L <= l && r <= R) {
  70. add[x] += num; Max[x] += num;
  71. return;
  72. }
  73. Down(x);
  74. int mid = (l + r) >> 1;
  75. if (L <= mid) Change(L, R, num, l, mid, x<<1);
  76. if (mid < R) Change(L, R, num, mid+1, r, x<<1|1);
  77. Up(x);
  78. }
  79. int Query(int L, int R, int l, int r, int x) {
  80. if (L == 0 || R == 0) return 0;
  81. if (L <= l && r <= R) return Max[x];
  82. Down(x);
  83. int mid = (l+r) >> 1;
  84. int res = -INF;
  85. if (L <= mid) res = max(res, Query(L, R, l, mid, x<<1));
  86. if (R > mid) res = max(res, Query(L, R, mid+1, r, x<<1|1));
  87. return res;
  88. }
  89. int main()
  90. {
  91. int tt = 0, i, a, x, y;
  92. while (~scanf("%d%d%d", &n, &m, &q))
  93. {
  94. init();
  95. for (i = 1; i <= n; i++)
  96. {
  97. scanf("%d", &rad[i]);
  98. rad[i] = log2(rad[i]);
  99. }
  100. for (i = 1; i <= m; i++)
  101. {
  102. scanf("%d%d%d", &a, &x, &y);
  103. if (a == 1)
  104. {
  105. edge[x].push_back(y);
  106. edge[y].push_back(x);
  107. }
  108. else f[sf(x)] = sf(y);
  109. }
  110. for (i = 1; i <= n; i++)
  111. for (auto& x: edge[i])
  112. lnk[sf(i)].push_back(Edge{sf(x), i, rad[i] - rad[x]});
  113. for (i = 1; i <= n; i++)
  114. if (sf(i) == i && !rt[i])
  115. dfs(i, i, i, 0);
  116. Build(1, pos, 1);
  117. printf("Case #%d:\n", ++tt);
  118. while (q--)
  119. {
  120. scanf("%d%d%d", &a, &x, &y);
  121. if (a == 1)
  122. {
  123. y = log2(y);
  124. int fx = sf(x);
  125. if (up[x]) Change(l[fx], r[fx], rad[x]-y, 1, pos, 1);
  126. if (ll[x] <= rr[x]) Change(ll[x], rr[x], y-rad[x], 1, pos, 1);
  127. rad[x] = y;
  128. } else {
  129. x = sf(x);
  130. int km = Query(l[rt[x]], r[rt[x]], 1, pos, 1);
  131. int k = Query(l[x], l[x], 1, pos, 1);
  132. double au = log2(y) + km - k;
  133. printf("%.3f\n", au*ln2);
  134. }
  135. }
  136. }
  137. }

  

HDU 6039 - Gear Up | 2017 Multi-University Training Contest 1的更多相关文章

  1. hdu 6039 Gear Up

    题 OvO http://acm.hdu.edu.cn/showproblem.php?pid=6039 (2017 Multi-University Training Contest 1 1007) ...

  2. HDU 6170 - Two strings | 2017 ZJUT Multi-University Training 9

    /* HDU 6170 - Two strings [ DP ] | 2017 ZJUT Multi-University Training 9 题意: 定义*可以匹配任意长度,.可以匹配任意字符,问 ...

  3. hdu 6301 Distinct Values (2018 Multi-University Training Contest 1 1004)

    Distinct Values Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)T ...

  4. hdu 5288 OO’s Sequence(2015 Multi-University Training Contest 1)

    OO's Sequence                                                          Time Limit: 4000/2000 MS (Jav ...

  5. hdu 5416 CRB and Tree(2015 Multi-University Training Contest 10)

    CRB and Tree                                                             Time Limit: 8000/4000 MS (J ...

  6. HDU 6039 Gear Up(线段树+并查集)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=6039 [题目大意] 给出一些齿轮,有些齿轮是边相连,也就是拥有相同的线速度, 有的齿轮是轴相连,也 ...

  7. HDU 4944 FSF’s game(2014 Multi-University Training Contest 7)

    思路:  ans[n]=  ans[n-1] + { (n,1),(n,2).....(n,n)}  现在任务 是 计算  { (n,1),(n,2).....(n,n)}(k=n的任意因子) 很明显 ...

  8. HDU 4940 Destroy Transportation system(2014 Multi-University Training Contest 7)

    思路:无源汇有上下界可行流判定, 原来每条边转化成  下界为D  上界为 D+B   ,判断是否存在可行流即可. 为什么呢?  如果存在可行流  那么说明对于任意的 S 集合流出的肯定等于 流入的, ...

  9. HDU 4627 The Unsolvable Problem 2013 Multi-University Training Contest 3

    给你一个数 n ( 2 <= n <= 109 ),现在需要你找到一对数a, b (a + b = n),并且使得LCM(a, b)尽可能的大,然后输出最大的 LCM(a, b). (为什 ...

随机推荐

  1. Android的视图(View)组件

    Android的绝大部分UI组件都放在android.widget包及其子包.android,view包及其子包中,Android应用的所有UI组件都继承了View类,View组件非常类似于Swing ...

  2. selenium的使用与chromedriver的下载配置

    Selenium是一个web自动化测试工具,最初是为网站自动化测试而开发的,Selenium可以直接运行在浏览器上,它支持所有主流的浏览器,可以接受指令,让浏览器自动加载页面,获得需要的数据,甚至页面 ...

  3. Linux就该这么学——初识vim编辑器

    在Linux系统中一切都是文件,而配置一个服务就是在修改其配置文件的参数 初识Vim编辑器 Vim编辑器顾名思义就是用来编写脚本程序的”记事本” Vim编辑器模式 : 命令模式 : 控制光标移动,可对 ...

  4. 深入理解Redux之手写React-Redux

    React-Redux主要由两部分组成,一是Provider(提供者),顾名思义作用就是提供状态数据. 另一部分是connect函数,它的作用是把UI组件和状态数据“连接”起来,实现了Model和Vi ...

  5. mybatis调用java类

    在mybatis的映射xml文件调用java类的方法: 使用的是OGNL表达式,表达式格式为:${@prefix@methodName(传递参数名称)} 1.如下代码所示:方法必须为静态方法:以下我只 ...

  6. Spingboot+Mybatis+Oracle项目配置

    配置过程参考: 项目创建:http://how2j.cn/k/springboot/springboot-eclipse/1640.html 集成Mybatis使用Oracle:https://www ...

  7. pymssql文档(转)

    pymssql methods set_max_connections(number) -- Sets maximum number of simultaneous database connecti ...

  8. O035、Nova Suspend / Rescue 操作详解

    参考https://www.cnblogs.com/CloudMan6/p/5503501.html   Suspend / Resume   有时候需要长时间暂停 instance , 可以通过 S ...

  9. js下载blob的形式

    前端构建blob的方式就是通过服务器返回的文件来创建blob,需要知道文件在服务器的具体路径,用bob创建object url对象,添加到a标签上,然后触发,blob有两个问题,1.对浏览器有兼容性限 ...

  10. nginx之健康检查

    正常情况下,nginx做反向代理,如果后端节点服务器宕掉的话,nginx默认是不能把这台realserver踢出upstream负载集群的,所以还会有请求转发到后端的这台realserver上面,这样 ...