读入挂

  1. inline void read(int &v)
  2. {
  3. v = ;
  4. char c = ;
  5. int p = ;
  6. while (c < '' || c > '')
  7. {
  8. if (c == '-')
  9. {
  10. p = -;
  11. }
  12. c = getchar();
  13. }
  14. while (c >= '' && c <= '')
  15. {
  16. v = (v << ) + (v << ) + c - '';
  17. c = getchar();
  18. }
  19. v *= p;
  20. }

基本模板

离线:

  1. /*Huyyt*/
  2. #include<bits/stdc++.h>
  3. #define mem(a,b) memset(a,b,sizeof(a))
  4. #define pb push_back
  5. using namespace std;
  6. typedef long long ll;
  7. typedef unsigned long long ull;
  8. using namespace std;
  9. const int MAXN = 1e5 + , MAXM = 1e5 + ;
  10. const int MAXQ = 1e5 + ;
  11. int to[MAXM << ], nxt[MAXM << ], Head[MAXN], ed = ;
  12. int value[MAXM << ];
  13. inline void addedge(int u, int v, int val)
  14. {
  15. to[++ed] = v;
  16. nxt[ed] = Head[u];
  17. value[ed] = val;
  18. Head[u] = ed;
  19. }
  20. int fa[MAXN], d[MAXN], vis[MAXN], LCA[MAXQ], ans[MAXQ];
  21. vector<int> query[MAXQ], query_id[MAXQ];
  22. void add_query(int x, int y, int id)
  23. {
  24. query[x].push_back(y), query_id[x].push_back(id);
  25. query[y].push_back(x), query_id[y].push_back(id);
  26. }
  27. int get(int x)
  28. {
  29. if (x == fa[x])
  30. {
  31. return x;
  32. }
  33. return fa[x] = get(fa[x]);
  34. }
  35. void tarjan(int x)
  36. {
  37. vis[x] = ;
  38. for (int v, i = Head[x]; i; i = nxt[i])
  39. {
  40. v = to[i];
  41. if (vis[v])
  42. {
  43. continue;
  44. }
  45. d[v] = d[x] + value[i];
  46. tarjan(v);
  47. fa[v] = x;
  48. }
  49. for (int i = ; i < query[x].size(); i++)
  50. {
  51. int v = query[x][i], id = query_id[x][i];
  52. if (vis[v] == )
  53. {
  54. LCA[id] = get(v);
  55. ans[id] = min(ans[id], d[x] + d[v] - * d[LCA[id]]);
  56. }
  57. }
  58. vis[x] = ;
  59. }
  60. int n, m;
  61. int u, v, z;
  62. int main()
  63. {
  64. int T;
  65. scanf("%d", &T);
  66. while (T--)
  67. {
  68. scanf("%d %d", &n, &m);
  69. for (int i = ; i <= n; i++)
  70. {
  71. vis[i] = Head[i] = , fa[i] = i;
  72. query[i].clear(), query_id[i].clear();
  73. }
  74. ed = ;
  75. for (int i = ; i < n; i++)
  76. {
  77. scanf("%d %d %d", &u, &v, &z);
  78. addedge(u, v, z), addedge(v, u, z);
  79. }
  80. for (int i = ; i <= m; i++)
  81. {
  82. scanf("%d %d", &u, &v);
  83. if (u == v)
  84. {
  85. ans[i] = ;
  86. LCA[i] = u;
  87. }
  88. else
  89. {
  90. add_query(u, v, i);
  91. ans[i] = << ;
  92. }
  93. }
  94. tarjan();
  95. for (int i = ; i <= m; i++)
  96. {
  97. printf("%d\n", ans[i]);
  98. }
  99. }
  100. return ;
  101. }

//HDU2586

倍增:

  1. for (int j=;j<=;j++){
  2. for (int i=;i<=n;i++) f[i][j]=f[f[i][j-]][j-],
  3. minn[i][j]=min(minn[i][j-],minn[f[i][j-]][j-]);
  4. }
  5. int lca(int x,int y){
  6. if (dep[x]<dep[y]) swap(x,y);
  7. int tmp=dep[x]-dep[y];
  8. for (int i=;i<=;i++){
  9. if (tmp&(<<i)) x=f[x][i];
  10. }
  11. if (x==y) return x;
  12. for (int i=;i>=;i--){
  13. if (f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
  14. }
  15. return f[x][];
  16. }
  17. int dist(int x,int y){
  18. if (dep[x]<dep[y]) swap(x,y);
  19. int tmp=dep[x]-dep[y],ret=1e9;
  20. for (int i=;i<=;i++){
  21. if (tmp&(<<i)) ret=min(ret,minn[x][i]),x=f[x][i];
  22. }
  23. return ret;
  24. }

HDU 2586  单树带权LCA

在线:

①倍增

  1. /* Huyyt */
  2. #include <bits/stdc++.h>
  3. using namespace std;
  4. const int maxn = ; //点的最大值
  5. const int maxl = ; //深度的最大值
  6. typedef struct
  7. {
  8. int from, to, w;
  9. } edge; //这个结构体用来存储边
  10. vector<edge> edges;
  11. vector<int> G[maxn];
  12. //保存边的数组
  13. int grand[maxn][maxl]; //x向上跳2^i次方的节点,x到他上面祖先2^i次方的距离
  14. int gw[maxn][maxl]; //维护距离的数组
  15. int depth[maxn];//深度
  16. int root;
  17. int n, m;
  18. int N; //N的意思是最多能跳几层
  19. void addedge(int x, int y, int w) //把边保存起来的函数
  20. {
  21. edge a = {x, y, w}, b = {y, x, w};
  22. edges.push_back(a);
  23. edges.push_back(b);
  24. G[x].push_back(edges.size() - );
  25. G[y].push_back(edges.size() - );
  26. }
  27. void dfs(int x)//dfs建图
  28. {
  29. for (int i = ; i <= N; i++) //第一个几点就全部都是0,第二个节点就有变化了,不理解的话建议复制代码输出下这些数组
  30. {
  31. grand[x][i] = grand[grand[x][i - ]][i - ]; //倍增 2^i=2^(i-1)+2^(i-1)
  32. gw[x][i] = gw[x][i - ] + gw[grand[x][i - ]][i - ]; //维护一个距离数组
  33. // if(grand[x][i]==0) break;
  34. }
  35. for (int i = ; i < G[x].size(); i++)
  36. {
  37. edge e = edges[G[x][i]];
  38. if (e.to != grand[x][]) //这里我们保存的是双向边所以与他相连的边不是他父亲就是他儿子父亲的话就不能执行,不然就死循环了。
  39. {
  40. depth[e.to] = depth[x] + ; //他儿子的深度等于他爸爸的加1
  41. grand[e.to][] = x; //与x相连那个节点的父亲等于x
  42. gw[e.to][] = e.w; //与x相连那个节点的距离等于这条边的距离
  43. dfs(e.to);//深搜往下面建
  44. }
  45. }
  46. }
  47. void Init()
  48. {
  49. //n为节点个数
  50. N = floor(log(n + 0.0) / log(2.0));//最多能跳的2^i祖先
  51. depth[root] = ; //根结点的祖先不存在,用-1表示
  52. memset(grand, , sizeof(grand));
  53. memset(gw, , sizeof(gw));
  54. dfs(root);//以1为根节点建树
  55. }
  56. int lca(int a, int b)
  57. {
  58. if (depth[a] > depth[b])
  59. {
  60. swap(a, b); //保证a在b上面,便于计算
  61. }
  62. int ans = ;
  63. for (int i = N; i >= ; i--) //类似于二进制拆分,从大到小尝试
  64. {
  65. if (depth[a] < depth[b] && depth[grand[b][i]] >= depth[a]) //a在b下面且b向上跳后不会到a上面
  66. {
  67. ans += gw[b][i], b = grand[b][i]; //先把深度较大的b往上跳
  68. }
  69. }
  70. if (a == b)
  71. {
  72. return ans;
  73. }
  74. for (int j = N; j >= ; j--) //在同一高度了,他们一起向上跳,跳他们不相同节点,当全都跳完之后grand【a】【0】就是lca,上面有解释哈。
  75. {
  76. if (grand[a][j] != grand[b][j])
  77. {
  78. ans += gw[a][j];
  79. ans += gw[b][j];
  80. a = grand[a][j];
  81. b = grand[b][j];
  82. }
  83. }
  84. if (a != b) //a等于b的情况就是上面土色字体的那种情况
  85. {
  86. ans += gw[a][], ans += gw[b][];
  87. }
  88. return ans;
  89. }
  90. int main()
  91. {
  92. depth[] = -;
  93. int t ;
  94. scanf("%d", &t);
  95. while (t--)
  96. {
  97. root = ;
  98. scanf("%d%d", &n, &m);
  99. for (int i = ; i < n; i++)
  100. {
  101. int x, y, w;
  102. scanf("%d%d%d", &x, &y, &w);
  103. addedge(x, y, w);
  104. }
  105. Init();
  106. for (int i = ; i <= m; i++)
  107. {
  108. int x, y;
  109. scanf("%d%d", &x, &y);
  110. printf("%d\n", lca(x, y));
  111. }
  112. }
  113. }

离线:

②Tarjan

  1. /*Huyyt*/
  2. #include<bits/stdc++.h>
  3. using namespace std;
  4. const int MAXN = ;//点的最大值
  5. const int MAXQ = ;//查询数的最大值
  6. inline int readint()
  7. {
  8. char c = getchar();
  9. int ans = ;
  10. while (c < '' || c > '')
  11. {
  12. c = getchar();
  13. }
  14. while (c >= '' && c <= '')
  15. {
  16. ans = ans * + c - '', c = getchar();
  17. }
  18. return ans;
  19. }
  20. //并查集部分
  21. int F[MAXN];//需要初始化为-1
  22. int find(int x)
  23. {
  24. if (F[x] == -)
  25. {
  26. return x;
  27. }
  28. return F[x] = find(F[x]);
  29. }
  30. void bing(int u, int v)
  31. {
  32. int t1 = find(u);
  33. int t2 = find(v);
  34. if (t1 != t2)
  35. {
  36. F[t1] = t2;
  37. }
  38. }
  39. bool vis[MAXN];//访问标记
  40. int ancestor[MAXN];//祖先
  41. int distence[MAXN];
  42. struct Edge
  43. {
  44. int to, next, dis;
  45. } edge[MAXN * ];
  46. int head[MAXN], tot;
  47. void addedge(int u, int v, int d)
  48. {
  49. edge[tot].to = v;
  50. edge[tot].dis = d;
  51. edge[tot].next = head[u];
  52. head[u] = tot++;
  53. }
  54. struct Query
  55. {
  56. int q, next;
  57. int index;//查询编号
  58. } query[MAXQ * ];
  59. int answer[MAXQ];//存储最后的查询结果,下标0~Q-1
  60. int h[MAXQ];
  61. int tt;
  62. int Q;
  63. void add_query(int u, int v, int index)
  64. {
  65. query[tt].q = v;
  66. query[tt].next = h[u];
  67. query[tt].index = index;
  68. h[u] = tt++;
  69. query[tt].q = u;
  70. query[tt].next = h[v];
  71. query[tt].index = index;
  72. h[v] = tt++;
  73. }
  74. void init()
  75. {
  76. tot = ;
  77. memset(head, -, sizeof(head));
  78. memset(distence, , sizeof(distence));
  79. tt = ;
  80. memset(h, -, sizeof(h));
  81. memset(vis, false, sizeof(vis));
  82. memset(F, -, sizeof(F));
  83. memset(ancestor, , sizeof(ancestor));
  84. }
  85. void getdistence(int x, int pre)
  86. {
  87. for (int i = head[x]; i != -; i = edge[i].next)
  88. {
  89. int v = edge[i].to;
  90. if (v == pre)
  91. {
  92. continue;
  93. }
  94. distence[v] = distence[x] + edge[i].dis;
  95. getdistence(v, x);
  96. }
  97. }
  98. void LCA(int u)
  99. {
  100. ancestor[u] = u;
  101. vis[u] = true;
  102. for (int i = head[u]; i != -; i = edge[i].next)
  103. {
  104. int v = edge[i].to;
  105. if (vis[v])
  106. {
  107. continue;
  108. }
  109. LCA(v);
  110. bing(u, v);
  111. ancestor[find(u)] = u;
  112. }
  113. for (int i = h[u]; i != -; i = query[i].next)
  114. {
  115. int v = query[i].q;
  116. if (vis[v])
  117. {
  118. answer[query[i].index] = distence[v] + distence[u] - * distence[ancestor[find(v)]];
  119. }
  120. }
  121. }
  122. bool flag[MAXN];
  123. int main()
  124. {
  125. int T;
  126. T = readint();
  127. int n;
  128. int u, v, k;
  129. int len;
  130. while (T--)
  131. {
  132. n = readint();
  133. Q = readint();
  134. init();
  135. memset(flag, false, sizeof(flag));
  136. for (int i = ; i < n; i++)
  137. {
  138. u = readint();
  139. v = readint();
  140. len = readint();
  141. flag[v] = true;
  142. addedge(u, v, len);
  143. addedge(v, u, len);
  144. }
  145. for (int i = ; i < Q; i++)
  146. {
  147. u = readint();
  148. v = readint();
  149. add_query(u, v, i);
  150. }
  151. int root;
  152. for (int i = ; i <= n; i++)
  153. if (!flag[i])
  154. {
  155. root = i;
  156. break;
  157. }
  158. distence[root] = ;
  159. getdistence(root, -);
  160. LCA(root);
  161. for (int i = ; i < Q; i++)
  162. {
  163. cout << answer[i] << endl;
  164. }
  165. }
  166. return ;
  167. }

hihocoder 1062   多树不带权LCA

离线:

①Tarjan

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = ;
  4. const int MAXQ = ;//查询数的最大值
  5. inline int readint()
  6. {
  7. char c = getchar();
  8. int ans = ;
  9. while (c < '' || c > '')
  10. {
  11. c = getchar();
  12. }
  13. while (c >= '' && c <= '')
  14. {
  15. ans = ans * + c - '', c = getchar();
  16. }
  17. return ans;
  18. }
  19. //并查集部分
  20. int F[MAXN];//需要初始化为-1
  21. int find(int x)
  22. {
  23. if (F[x] == -)
  24. {
  25. return x;
  26. }
  27. return F[x] = find(F[x]);
  28. }
  29. void bing(int u, int v)
  30. {
  31. int t1 = find(u);
  32. int t2 = find(v);
  33. if (t1 != t2)
  34. {
  35. F[t1] = t2;
  36. }
  37. }
  38. //************************
  39. bool vis[MAXN];//访问标记
  40. int ancestor[MAXN];//祖先
  41. struct Edge
  42. {
  43. int to, next;
  44. } edge[MAXN * ];
  45. int head[MAXN], tot;
  46. void addedge(int u, int v)
  47. {
  48. edge[tot].to = v;
  49. edge[tot].next = head[u];
  50. head[u] = tot++;
  51. }
  52. struct Query
  53. {
  54. int q, next;
  55. int index;//查询编号
  56. } query[MAXQ * ];
  57. int answer[MAXQ];//存储最后的查询结果,下标0~Q-1
  58. int finalfather[MAXN];
  59. void getfather(int x, int pre, int aim)
  60. {
  61. finalfather[x] = aim;
  62. for (int i = head[x]; i != -; i = edge[i].next)
  63. {
  64. int v = edge[i].to;
  65. if (v == pre)
  66. {
  67. continue;
  68. }
  69. getfather(v, x, aim);
  70. }
  71. }
  72. int h[MAXQ];
  73. int tt;
  74. int Q;
  75. void add_query(int u, int v, int index)
  76. {
  77. query[tt].q = v;
  78. query[tt].next = h[u];
  79. query[tt].index = index;
  80. h[u] = tt++;
  81. query[tt].q = u;
  82. query[tt].next = h[v];
  83. query[tt].index = index;
  84. h[v] = tt++;
  85. }
  86. void init()
  87. {
  88. tot = ;
  89. memset(head, -, sizeof(head));
  90. tt = ;
  91. memset(h, -, sizeof(h));
  92. memset(vis, false, sizeof(vis));
  93. memset(F, -, sizeof(F));
  94. memset(ancestor, , sizeof(ancestor));
  95. }
  96. void LCA(int u)
  97. {
  98. ancestor[u] = u;
  99. vis[u] = true;
  100. for (int i = head[u]; i != -; i = edge[i].next)
  101. {
  102. int v = edge[i].to;
  103. if (vis[v])
  104. {
  105. continue;
  106. }
  107. LCA(v);
  108. bing(u, v);
  109. ancestor[find(u)] = u;
  110. }
  111. for (int i = h[u]; i != -; i = query[i].next)
  112. {
  113. int v = query[i].q;
  114. if (vis[v])
  115. {
  116. //cout << " " << u << " " << v << " " << find(u) << " " << find(v)<<endl;
  117. if (finalfather[v] != finalfather[u])
  118. {
  119. answer[query[i].index] = -;
  120. }
  121. answer[query[i].index] = ancestor[find(v)];
  122. }
  123. }
  124. }
  125. map<string, int> mp;
  126. map<int, string> mpback;
  127. int Qflag[MAXQ];
  128. int pop = ;
  129. string anser[MAXN];
  130. string from, to;
  131. void getnum(string x)
  132. {
  133. if (mp[x])
  134. {
  135. return ;
  136. }
  137. mp[x] = ++pop;
  138. mpback[pop] = x;
  139. return ;
  140. }
  141. bool flag[MAXN];
  142. int main()
  143. {
  144. int n;
  145. int u, v, k;
  146. while (scanf("%d", &n) == )
  147. {
  148. for (int i = ; i < MAXN; i++)
  149. {
  150. anser[i] = "";
  151. }
  152. init();
  153. memset(flag, false, sizeof(flag));
  154. for (int i = ; i <= n; i++)
  155. {
  156. cin >> from >> to;
  157. getnum(from);
  158. getnum(to);
  159. //cout << mp[from] << " " << mp[to] << endl;
  160. flag[mp[to]] = true;
  161. addedge(mp[from], mp[to]);
  162. addedge(mp[to], mp[from]);
  163. }
  164. Q = readint();
  165. for (int i = ; i < Q; i++)
  166. {
  167. // u = readint();
  168. // v = readint();
  169. // add_query(u, v, i);
  170. cin >> from >> to;
  171. if (from == to)
  172. {
  173. anser[i] = from;
  174. }
  175. else
  176. {
  177. if (mp.find(from) == mp.end() || mp.find(to) == mp.end())
  178. {
  179. anser[i] = "-1";
  180. }
  181. else
  182. {
  183. add_query(mp[from], mp[to], i);
  184. }
  185. }
  186. }
  187. int root;
  188. for (int i = ; i <= pop; i++)
  189. {
  190. if (!flag[i])
  191. {
  192. getfather(i, -, i);
  193. }
  194. }
  195. for (int i = ; i <= pop; i++)
  196. if (!flag[i])
  197. {
  198. root = i;
  199. LCA(root);
  200. }
  201. for (int i = ; i < Q; i++)
  202. {
  203.  
  204. if (anser[i] != "")
  205. {
  206. cout << anser[i] << endl;
  207. }
  208. else
  209. {
  210. if (answer[i] == -)
  211. {
  212. cout << - << endl;
  213. }
  214. else
  215. {
  216. cout << mpback[answer[i]] << endl;
  217. }
  218. }
  219. }
  220. }
  221. return ;
  222. }

在线:

①倍增

  1. /* Huyyt */
  2. #include <bits/stdc++.h>
  3. using namespace std;
  4. const int maxn = ; //点的最大值
  5. const int maxl = ; //深度的最大值
  6. typedef struct
  7. {
  8. int from, to, w;
  9. } edge; //这个结构体用来存储边
  10. vector<edge> edges;
  11. vector<int> G[maxn];
  12. //保存边的数组
  13. int grand[maxn][maxl]; //x向上跳2^i次方的节点,x到他上面祖先2^i次方的距离
  14. int gw[maxn][maxl]; //维护距离的数组
  15. //int gwmax[maxn][maxl]; //维护边权最大值的数组
  16. int depth[maxn];//深度
  17. int root;
  18. int n, m;
  19. int N; //N的意思是最多能跳几层
  20. map<string, int> mp;
  21. map<int, string> mpback;
  22. int pop = ;
  23. string from, to;
  24. void addedge(int x, int y, int w) //把边保存起来的函数
  25. {
  26. edge a = {x, y, w}, b = {y, x, w};
  27. edges.push_back(a);
  28. edges.push_back(b);
  29. G[x].push_back(edges.size() - );
  30. G[y].push_back(edges.size() - );
  31. }
  32. void dfs(int x)//dfs建图
  33. {
  34. for (int i = ; i <= N; i++) //第一个几点就全部都是0,第二个节点就有变化了,不理解的话建议复制代码输出下这些数组
  35. {
  36. grand[x][i] = grand[grand[x][i - ]][i - ]; //倍增 2^i=2^(i-1)+2^(i-1)
  37. gw[x][i] = gw[x][i - ] + gw[grand[x][i - ]][i - ]; //维护一个距离数组
  38. //gwmax[x][i]=max(gwmax[x][i-1],gw[grand[x][i-1]][i-1]);
  39. // if(grand[x][i]==0) break;
  40. }
  41. for (int i = ; i < G[x].size(); i++)
  42. {
  43. edge e = edges[G[x][i]];
  44. if (e.to != grand[x][]) //这里我们保存的是双向边所以与他相连的边不是他父亲就是他儿子父亲的话就不能执行,不然就死循环了。
  45. {
  46. depth[e.to] = depth[x] + ; //他儿子的深度等于他爸爸的加1
  47. grand[e.to][] = x; //与x相连那个节点的父亲等于x
  48. gw[e.to][] = e.w; //与x相连那个节点的距离等于这条边的距离
  49. //gwmax[e.to][0]=e.w;
  50. dfs(e.to);//深搜往下面建
  51. }
  52. }
  53. }
  54. void Init()
  55. {
  56. //n为节点个数
  57. N = floor(log(maxn + 0.0) / log(2.0));//最多能跳的2^i祖先
  58. depth[root] = ; //根结点的祖先不存在,用-1表示
  59. depth[] = -;
  60. memset(grand, , sizeof(grand));
  61. //memset(gw, 0, sizeof(gw));
  62. dfs(root);//以根节点建树
  63. }
  64. int lca(int a, int b)
  65. {
  66. if (depth[a] > depth[b])
  67. {
  68. swap(a, b); //保证a在b上面,便于计算
  69. }
  70. int ans = ;
  71. for (int i = N; i >= ; i--) //类似于二进制拆分,从大到小尝试
  72. {
  73. if (depth[a] < depth[b] && depth[grand[b][i]] >= depth[a]) //a在b下面且b向上跳后不会到a上面
  74. {
  75. ans += gw[b][i], b = grand[b][i]; //先把深度较大的b往上跳
  76. }
  77. }
  78. if (a == b)
  79. {
  80. return a;
  81. }
  82. for (int j = N; j >= ; j--) //在同一高度了,他们一起向上跳,跳他们不相同节点,当全都跳完之后grand【a】【0】就是lca,上面有解释哈。
  83. {
  84. if (grand[a][j] != grand[b][j])
  85. {
  86. ans += gw[a][j];
  87. ans += gw[b][j];
  88. a = grand[a][j];
  89. b = grand[b][j];
  90. }
  91. }
  92. if (a != b) //a等于b的情况就是上面土色字体的那种情况
  93. {
  94. ans += gw[a][], ans += gw[b][];
  95. }
  96. if (grand[a][] == && grand[b][] == && a != b)
  97. {
  98. return -;
  99. }
  100. return grand[a][];
  101. }
  102. void getnum(string x)
  103. {
  104. if (mp[x])
  105. {
  106. return ;
  107. }
  108. mp[x] = ++pop;
  109. mpback[pop] = x;
  110. return ;
  111. }
  112. int in[maxn];
  113. int main()
  114. {
  115. N = floor(log(maxn + 0.0) / log(2.0));
  116. depth[] = -;
  117. cin >> n;
  118. for (int i = ; i <= n; i++)
  119. {
  120. cin >> from >> to;
  121. getnum(from);
  122. getnum(to);
  123. //cout << mp[from] << " " << mp[to] << endl;
  124. addedge(mp[from], mp[to], );
  125. in[mp[to]]++;
  126. }
  127. for (int i = ; i <= pop; i++)
  128. {
  129. if (in[i] == )
  130. {
  131. root = i;
  132. dfs(root);
  133. }
  134. }
  135. cin >> m;
  136. for (int i = ; i <= m; i++)
  137. {
  138. cin >> from >> to;
  139. if (from == to)
  140. {
  141. cout << from << endl;
  142. }
  143. else
  144. {
  145. if (mp.find(from) == mp.end() || mp.find(to) == mp.end())
  146. {
  147. cout << - << endl;
  148. }
  149. else
  150. {
  151. int aim = lca(mp[from], mp[to]);
  152. if (aim == -)
  153. {
  154. cout << - << endl;
  155. }
  156. else
  157. {
  158. cout << mpback[aim] << endl;
  159. }
  160. }
  161. }
  162.  
  163. }
  164. }

hihocoder 1067   单树不带权LCA

离线:

①Tarjan

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = ;
  4. const int MAXQ = ;//查询数的最大值
  5. inline int readint()
  6. {
  7. char c = getchar();
  8. int ans = ;
  9. while (c < '' || c > '')
  10. {
  11. c = getchar();
  12. }
  13. while (c >= '' && c <= '')
  14. {
  15. ans = ans * + c - '', c = getchar();
  16. }
  17. return ans;
  18. }
  19. //并查集部分
  20. int F[MAXN];//需要初始化为-1
  21. int find(int x)
  22. {
  23. if (F[x] == -)
  24. {
  25. return x;
  26. }
  27. return F[x] = find(F[x]);
  28. }
  29. void bing(int u, int v)
  30. {
  31. int t1 = find(u);
  32. int t2 = find(v);
  33. if (t1 != t2)
  34. {
  35. F[t1] = t2;
  36. }
  37. }
  38. //************************
  39. bool vis[MAXN];//访问标记
  40. int ancestor[MAXN];//祖先
  41. struct Edge
  42. {
  43. int to, next;
  44. } edge[MAXN * ];
  45. int head[MAXN], tot;
  46. void addedge(int u, int v)
  47. {
  48. edge[tot].to = v;
  49. edge[tot].next = head[u];
  50. head[u] = tot++;
  51. }
  52. struct Query
  53. {
  54. int q, next;
  55. int index;//查询编号
  56. } query[MAXQ * ];
  57. int answer[MAXQ];//存储最后的查询结果,下标0~Q-1
  58. int h[MAXQ];
  59. int tt;
  60. int Q;
  61. void add_query(int u, int v, int index)
  62. {
  63. query[tt].q = v;
  64. query[tt].next = h[u];
  65. query[tt].index = index;
  66. h[u] = tt++;
  67. query[tt].q = u;
  68. query[tt].next = h[v];
  69. query[tt].index = index;
  70. h[v] = tt++;
  71. }
  72. void init()
  73. {
  74. tot = ;
  75. memset(head, -, sizeof(head));
  76. tt = ;
  77. memset(h, -, sizeof(h));
  78. memset(vis, false, sizeof(vis));
  79. memset(F, -, sizeof(F));
  80. memset(ancestor, , sizeof(ancestor));
  81. }
  82. void LCA(int u)
  83. {
  84. ancestor[u] = u;
  85. vis[u] = true;
  86. for (int i = head[u]; i != -; i = edge[i].next)
  87. {
  88. int v = edge[i].to;
  89. if (vis[v])
  90. {
  91. continue;
  92. }
  93. LCA(v);
  94. bing(u, v);
  95. ancestor[find(u)] = u;
  96. }
  97. for (int i = h[u]; i != -; i = query[i].next)
  98. {
  99. int v = query[i].q;
  100. if (vis[v])
  101. {
  102. answer[query[i].index] = ancestor[find(v)];
  103. }
  104. }
  105. }
  106. map<string, int> mp;
  107. map<int, string> mpback;
  108. int pop = ;
  109. string from, to;
  110. void getnum(string x)
  111. {
  112. if (mp[x])
  113. {
  114. return ;
  115. }
  116. mp[x] = ++pop;
  117. mpback[pop] = x;
  118. return ;
  119. }
  120. bool flag[MAXN];
  121. int Count_num[MAXN];
  122. int main()
  123. {
  124. //freopen("in.txt","r",stdin);
  125. //freopen("out.txt","w",stdout);
  126. int n;
  127. int u, v, k;
  128. while (scanf("%d", &n) == )
  129. {
  130. init();
  131. memset(flag, false, sizeof(flag));
  132. for (int i = ; i <= n; i++)
  133. {
  134. cin >> from >> to;
  135. getnum(from);
  136. getnum(to);
  137. flag[mp[to]]=true;
  138. addedge(mp[from],mp[to]);
  139. addedge(mp[to],mp[from]);
  140. }
  141. Q = readint();
  142. for (int i = ; i < Q; i++)
  143. {
  144. cin >> from >> to;
  145. add_query(mp[from],mp[to], i);
  146. }
  147. int root;
  148. for (int i = ; i <= n; i++)
  149. if (!flag[i])
  150. {
  151. root = i;
  152. break;
  153. }
  154. LCA(root);
  155. memset(Count_num, , sizeof(Count_num));
  156. for (int i = ; i < Q; i++)
  157. {
  158. cout<<mpback[answer[i]]<<endl;
  159. }
  160. }
  161. return ;
  162. }

在线:

①倍增

  1. /* Huyyt */
  2. #include <bits/stdc++.h>
  3. using namespace std;
  4. const int maxn = ; //点的最大值
  5. const int maxl = ; //深度的最大值
  6. typedef struct
  7. {
  8. int from, to, w;
  9. } edge; //这个结构体用来存储边
  10. vector<edge> edges;
  11. vector<int> G[maxn];
  12. //保存边的数组
  13. int grand[maxn][maxl]; //x向上跳2^i次方的节点,x到他上面祖先2^i次方的距离
  14. int gw[maxn][maxl]; //维护距离的数组
  15. //int gwmax[maxn][maxl]; //维护边权最大值的数组
  16. int depth[maxn];//深度
  17. int root;
  18. int n, m;
  19. int N; //N的意思是最多能跳几层
  20. map<string, int> mp;
  21. map<int, string> mpback;
  22. int pop = ;
  23. string from, to;
  24. void addedge(int x, int y, int w) //把边保存起来的函数
  25. {
  26. edge a = {x, y, w}, b = {y, x, w};
  27. edges.push_back(a);
  28. edges.push_back(b);
  29. G[x].push_back(edges.size() - );
  30. G[y].push_back(edges.size() - );
  31. }
  32. void dfs(int x)//dfs建图
  33. {
  34. for (int i = ; i <= N; i++) //第一个几点就全部都是0,第二个节点就有变化了,不理解的话建议复制代码输出下这些数组
  35. {
  36. grand[x][i] = grand[grand[x][i - ]][i - ]; //倍增 2^i=2^(i-1)+2^(i-1)
  37. gw[x][i] = gw[x][i - ] + gw[grand[x][i - ]][i - ]; //维护一个距离数组
  38. //gwmax[x][i]=max(gwmax[x][i-1],gw[grand[x][i-1]][i-1]);
  39. // if(grand[x][i]==0) break;
  40. }
  41. for (int i = ; i < G[x].size(); i++)
  42. {
  43. edge e = edges[G[x][i]];
  44. if (e.to != grand[x][]) //这里我们保存的是双向边所以与他相连的边不是他父亲就是他儿子父亲的话就不能执行,不然就死循环了。
  45. {
  46. depth[e.to] = depth[x] + ; //他儿子的深度等于他爸爸的加1
  47. grand[e.to][] = x; //与x相连那个节点的父亲等于x
  48. gw[e.to][] = e.w; //与x相连那个节点的距离等于这条边的距离
  49. //gwmax[e.to][0]=e.w;
  50. dfs(e.to);//深搜往下面建
  51. }
  52. }
  53. }
  54. void Init()
  55. {
  56. //n为节点个数
  57. N = floor(log(pop + 0.0) / log(2.0));//最多能跳的2^i祖先
  58. depth[root] = ; //根结点的祖先不存在,用-1表示
  59. depth[] = -;
  60. memset(grand, , sizeof(grand));
  61. memset(gw, , sizeof(gw));
  62. dfs(root);//以根节点建树
  63. }
  64. int lca(int a, int b)
  65. {
  66. if (depth[a] > depth[b])
  67. {
  68. swap(a, b); //保证a在b上面,便于计算
  69. }
  70. int ans = ;
  71. for (int i = N; i >= ; i--) //类似于二进制拆分,从大到小尝试
  72. {
  73. if (depth[a] < depth[b] && depth[grand[b][i]] >= depth[a]) //a在b下面且b向上跳后不会到a上面
  74. {
  75. ans += gw[b][i], b = grand[b][i]; //先把深度较大的b往上跳
  76. }
  77. }
  78. if (a == b)
  79. {
  80. return a;
  81. }
  82. for (int j = N; j >= ; j--) //在同一高度了,他们一起向上跳,跳他们不相同节点,当全都跳完之后grand【a】【0】就是lca,上面有解释哈。
  83. {
  84. if (grand[a][j] != grand[b][j])
  85. {
  86. ans += gw[a][j];
  87. ans += gw[b][j];
  88. a = grand[a][j];
  89. b = grand[b][j];
  90. }
  91. }
  92. if (a != b) //a等于b的情况就是上面土色字体的那种情况
  93. {
  94. ans += gw[a][], ans += gw[b][];
  95. }
  96. return grand[a][];
  97. }
  98. void getnum(string x)
  99. {
  100. if (mp[x])
  101. {
  102. return ;
  103. }
  104. mp[x] = ++pop;
  105. mpback[pop] = x;
  106. return ;
  107. }
  108. int main()
  109. {
  110. root = ;
  111. cin >> n;
  112. for (int i = ; i <= n; i++)
  113. {
  114. cin >> from >> to;
  115. getnum(from);
  116. getnum(to);
  117. //cout << mp[from] << " " << mp[to] << endl;
  118. addedge(mp[from], mp[to], );
  119. }
  120. Init();
  121. cin >> m;
  122. for (int i = ; i <= m; i++)
  123. {
  124. cin >> from >> to;
  125. //getnum(from), getnum(to);
  126. cout << mpback[lca(mp[from], mp[to])] << endl;
  127. }
  128. }

hihocoder 1069  在线单树不带权LCA

①倍增

  1. /* Huyyt */
  2. #include <bits/stdc++.h>
  3. using namespace std;
  4. const int maxn = ; //点的最大值
  5. const int maxl = ; //深度的最大值
  6. typedef struct
  7. {
  8. int from, to, w;
  9. } edge; //这个结构体用来存储边
  10. vector<edge> edges;
  11. vector<int> G[maxn];
  12. //保存边的数组
  13. int grand[maxn][maxl]; //x向上跳2^i次方的节点,x到他上面祖先2^i次方的距离
  14. int gw[maxn][maxl]; //维护距离的数组
  15. //int gwmax[maxn][maxl]; //维护边权最大值的数组
  16. int depth[maxn];//深度
  17. int root;
  18. int n, m;
  19. int N; //N的意思是最多能跳几层
  20. map<string, int> mp;
  21. map<int, string> mpback;
  22. int pop = ;
  23. string from, to;
  24. void addedge(int x, int y, int w) //把边保存起来的函数
  25. {
  26. edge a = {x, y, w}, b = {y, x, w};
  27. edges.push_back(a);
  28. edges.push_back(b);
  29. G[x].push_back(edges.size() - );
  30. G[y].push_back(edges.size() - );
  31. }
  32. void dfs(int x)//dfs建图
  33. {
  34. for (int i = ; i <= N; i++) //第一个几点就全部都是0,第二个节点就有变化了,不理解的话建议复制代码输出下这些数组
  35. {
  36. grand[x][i] = grand[grand[x][i - ]][i - ]; //倍增 2^i=2^(i-1)+2^(i-1)
  37. gw[x][i] = gw[x][i - ] + gw[grand[x][i - ]][i - ]; //维护一个距离数组
  38. //gwmax[x][i]=max(gwmax[x][i-1],gw[grand[x][i-1]][i-1]);
  39. // if(grand[x][i]==0) break;
  40. }
  41. for (int i = ; i < G[x].size(); i++)
  42. {
  43. edge e = edges[G[x][i]];
  44. if (e.to != grand[x][]) //这里我们保存的是双向边所以与他相连的边不是他父亲就是他儿子父亲的话就不能执行,不然就死循环了。
  45. {
  46. depth[e.to] = depth[x] + ; //他儿子的深度等于他爸爸的加1
  47. grand[e.to][] = x; //与x相连那个节点的父亲等于x
  48. gw[e.to][] = e.w; //与x相连那个节点的距离等于这条边的距离
  49. //gwmax[e.to][0]=e.w;
  50. dfs(e.to);//深搜往下面建
  51. }
  52. }
  53. }
  54. void Init()
  55. {
  56. //n为节点个数
  57. N = floor(log(pop + 0.0) / log(2.0));//最多能跳的2^i祖先
  58. depth[root] = ; //根结点的祖先不存在,用-1表示
  59. depth[] = -;
  60. memset(grand, , sizeof(grand));
  61. memset(gw, , sizeof(gw));
  62. dfs(root);//以根节点建树
  63. }
  64. int lca(int a, int b)
  65. {
  66. if (depth[a] > depth[b])
  67. {
  68. swap(a, b); //保证a在b上面,便于计算
  69. }
  70. int ans = ;
  71. for (int i = N; i >= ; i--) //类似于二进制拆分,从大到小尝试
  72. {
  73. if (depth[a] < depth[b] && depth[grand[b][i]] >= depth[a]) //a在b下面且b向上跳后不会到a上面
  74. {
  75. ans += gw[b][i], b = grand[b][i]; //先把深度较大的b往上跳
  76. }
  77. }
  78. if (a == b)
  79. {
  80. return a;
  81. }
  82. for (int j = N; j >= ; j--) //在同一高度了,他们一起向上跳,跳他们不相同节点,当全都跳完之后grand【a】【0】就是lca,上面有解释哈。
  83. {
  84. if (grand[a][j] != grand[b][j])
  85. {
  86. ans += gw[a][j];
  87. ans += gw[b][j];
  88. a = grand[a][j];
  89. b = grand[b][j];
  90. }
  91. }
  92. if (a != b) //a等于b的情况就是上面土色字体的那种情况
  93. {
  94. ans += gw[a][], ans += gw[b][];
  95. }
  96. return grand[a][];
  97. }
  98. void getnum(string x)
  99. {
  100. if (mp[x])
  101. {
  102. return ;
  103. }
  104. mp[x] = ++pop;
  105. mpback[pop] = x;
  106. return ;
  107. }
  108. int main()
  109. {
  110. root = ;
  111. cin >> n;
  112. for (int i = ; i <= n; i++)
  113. {
  114. cin >> from >> to;
  115. getnum(from);
  116. getnum(to);
  117. //cout << mp[from] << " " << mp[to] << endl;
  118. addedge(mp[from], mp[to], );
  119. }
  120. Init();
  121. cin >> m;
  122. for (int i = ; i <= m; i++)
  123. {
  124. cin >> from >> to;
  125. //getnum(from), getnum(to);
  126. cout << mpback[lca(mp[from], mp[to])] << endl;
  127. }
  128. }

codevs4605  在线单树不带权LCA

①倍增

  1. /* Huyyt */
  2. #include <bits/stdc++.h>
  3. using namespace std;
  4. const int maxn = ; //点的最大值
  5. const int maxl = ; //深度的最大值
  6. typedef struct
  7. {
  8. int from, to, w;
  9. } edge; //这个结构体用来存储边
  10. vector<edge> edges;
  11. vector<int> G[maxn];
  12. //保存边的数组
  13. int grand[maxn][maxl]; //x向上跳2^i次方的节点,x到他上面祖先2^i次方的距离
  14. int gw[maxn][maxl]; //维护距离的数组
  15. //int gwmax[maxn][maxl]; //维护边权最大值的数组
  16. int depth[maxn];//深度
  17. int root;
  18. int from, to;
  19. int n, m;
  20. int N; //N的意思是最多能跳几层
  21. void addedge(int x, int y, int w) //把边保存起来的函数
  22. {
  23. edge a = {x, y, w}, b = {y, x, w};
  24. edges.push_back(a);
  25. edges.push_back(b);
  26. G[x].push_back(edges.size() - );
  27. G[y].push_back(edges.size() - );
  28. }
  29. void dfs(int x)//dfs建图
  30. {
  31. for (int i = ; i <= N; i++) //第一个几点就全部都是0,第二个节点就有变化了,不理解的话建议复制代码输出下这些数组
  32. {
  33. grand[x][i] = grand[grand[x][i - ]][i - ]; //倍增 2^i=2^(i-1)+2^(i-1)
  34. gw[x][i] = gw[x][i - ] + gw[grand[x][i - ]][i - ]; //维护一个距离数组
  35. //gwmax[x][i]=max(gwmax[x][i-1],gw[grand[x][i-1]][i-1]);
  36. // if(grand[x][i]==0) break;
  37. }
  38. for (int i = ; i < G[x].size(); i++)
  39. {
  40. edge e = edges[G[x][i]];
  41. if (e.to != grand[x][]) //这里我们保存的是双向边所以与他相连的边不是他父亲就是他儿子父亲的话就不能执行,不然就死循环了。
  42. {
  43. depth[e.to] = depth[x] + ; //他儿子的深度等于他爸爸的加1
  44. grand[e.to][] = x; //与x相连那个节点的父亲等于x
  45. gw[e.to][] = e.w; //与x相连那个节点的距离等于这条边的距离
  46. //gwmax[e.to][0]=e.w;
  47. dfs(e.to);//深搜往下面建
  48. }
  49. }
  50. }
  51. void Init()
  52. {
  53. //n为节点个数
  54. N = floor(log(n + 0.0) / log(2.0));//最多能跳的2^i祖先
  55. depth[root] = ; //根结点的祖先不存在,用-1表示
  56. depth[] = -;
  57. memset(grand, , sizeof(grand));
  58. memset(gw, , sizeof(gw));
  59. dfs(root);//以根节点建树
  60. }
  61. int lca(int a, int b)
  62. {
  63. if (depth[a] > depth[b])
  64. {
  65. swap(a, b); //保证a在b上面,便于计算
  66. }
  67. int ans = ;
  68. for (int i = N; i >= ; i--) //类似于二进制拆分,从大到小尝试
  69. {
  70. if (depth[a] < depth[b] && depth[grand[b][i]] >= depth[a]) //a在b下面且b向上跳后不会到a上面
  71. {
  72. ans += gw[b][i], b = grand[b][i]; //先把深度较大的b往上跳
  73. }
  74. }
  75. if (a == b)
  76. {
  77. return a;
  78. }
  79. for (int j = N; j >= ; j--) //在同一高度了,他们一起向上跳,跳他们不相同节点,当全都跳完之后grand【a】【0】就是lca,上面有解释哈。
  80. {
  81. if (grand[a][j] != grand[b][j])
  82. {
  83. ans += gw[a][j];
  84. ans += gw[b][j];
  85. a = grand[a][j];
  86. b = grand[b][j];
  87. }
  88. }
  89. if (a != b) //a等于b的情况就是上面土色字体的那种情况
  90. {
  91. ans += gw[a][], ans += gw[b][];
  92. }
  93. return grand[a][];
  94. }
  95. int main()
  96. {
  97. root = ;
  98. cin >> n;
  99. for (int i = ; i <= n; i++)
  100. {
  101. cin >> to;
  102. if (to == )
  103. {
  104. root = i;
  105. continue;
  106. }
  107. addedge(to, i, );
  108. }
  109. Init();
  110. cin >> m;
  111. int anser = ;
  112. for (int i = ; i <= m; i++)
  113. {
  114. cin >> from >> to;
  115. from ^= anser;
  116. to ^= anser;
  117. anser = lca(from, to);
  118. cout << anser << endl;
  119. }
  120. }

②ST

  1. /*Huyyt*/
  2. #include<bits/stdc++.h>
  3. #define mem(a,b) memset(a,b,sizeof(a))
  4. #define pb push_back
  5. using namespace std;
  6. typedef long long ll;
  7. typedef unsigned long long ull;
  8. const int mod = 1e9 + ;
  9. const int gakki = + + + + 1e9;
  10. const int MAXN = 2e5 + , MAXM = 2e5 + ;
  11. int to[MAXM << ], nxt[MAXM << ], Head[MAXN], tot = ;
  12. inline void addedge(int u, int v)
  13. {
  14. to[++tot] = v;
  15. nxt[tot] = Head[u];
  16. Head[u] = tot;
  17. }
  18. int depth[ * MAXN], ver[ * MAXN], first[MAXN], dfs_clock = ;
  19. int dp[MAXN][];
  20. void dfs(int x, int fa, int deep)
  21. {
  22. ver[++dfs_clock] = x;
  23. first[x] = dfs_clock;
  24. depth[dfs_clock] = deep;
  25. for (int i = Head[x]; i; i = nxt[i])
  26. {
  27. int v = to[i];
  28. if (v != fa)
  29. {
  30. dfs(v, x, deep + );
  31. ver[++dfs_clock] = x;
  32. depth[dfs_clock] = deep;
  33. }
  34. }
  35. }
  36. void ST(int n)
  37. {
  38. for (int i = ; i <= n; i++)
  39. {
  40. dp[i][] = i;
  41. }
  42. for (int j = ; ( << j) <= n; j++)
  43. {
  44. for (int i = ; i + ( << j) - <= n; i++)
  45. {
  46. dp[i][j] = depth[dp[i][j - ]] < depth[dp[i + ( << (j - ))][j - ]] ? dp[i][j - ] : dp[i + ( << (j - ))][j - ];
  47. }
  48. }
  49. }
  50. int RMQ(int l, int r)
  51. {
  52. int k = (int)(log((double)(r-l+)) / log(2.0));
  53. return depth[dp[l][k]] < depth[dp[r - ( << k) + ][k]] ? dp[l][k] : dp[r - ( << k) + ][k];
  54. }
  55. int LCA(int u, int v)
  56. {
  57. int a = first[u], b = first[v];
  58. if (a > b)
  59. {
  60. swap(a, b);
  61. }
  62. int res = RMQ(a, b);
  63. return ver[res];
  64. }
  65. int main()
  66. {
  67. ios_base::sync_with_stdio();
  68. cin.tie();
  69. int root;
  70. int n, m, u, v;
  71. cin >> n;
  72. for (int i = ; i <= n; i++)
  73. {
  74. cin >> u;
  75. if (u == )
  76. {
  77. root = i;
  78. continue;
  79. }
  80. addedge(i, u), addedge(u, i);
  81. }
  82. dfs(root, , );
  83. ST(dfs_clock);
  84. int anser = ;
  85. cin >> m;
  86. for (int i = ; i <= m; i++)
  87. {
  88. cin >> u >> v;
  89. u = u ^ anser;
  90. v = v ^ anser;
  91. anser = LCA(u, v);
  92. cout << anser << endl;
  93. }
  94. return ;
  95. }

POJ1470   大量输入5e5询问LCA

①Tarjan

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = ;
  4. const int MAXQ = ;//查询数的最大值
  5. inline int readint()
  6. {
  7. char c = getchar();
  8. int ans = ;
  9. while (c < '' || c > '')
  10. {
  11. c = getchar();
  12. }
  13. while (c >= '' && c <= '')
  14. {
  15. ans = ans * + c - '', c = getchar();
  16. }
  17. return ans;
  18. }
  19. //并查集部分
  20. int F[MAXN];//需要初始化为-1
  21. int find(int x)
  22. {
  23. if (F[x] == -)
  24. {
  25. return x;
  26. }
  27. return F[x] = find(F[x]);
  28. }
  29. void bing(int u, int v)
  30. {
  31. int t1 = find(u);
  32. int t2 = find(v);
  33. if (t1 != t2)
  34. {
  35. F[t1] = t2;
  36. }
  37. }
  38. //************************
  39. bool vis[MAXN];//访问标记
  40. int ancestor[MAXN];//祖先
  41. struct Edge
  42. {
  43. int to, next;
  44. } edge[MAXN * ];
  45. int head[MAXN], tot;
  46. void addedge(int u, int v)
  47. {
  48. edge[tot].to = v;
  49. edge[tot].next = head[u];
  50. head[u] = tot++;
  51. }
  52.  
  53. struct Query
  54. {
  55. int q, next;
  56. int index;//查询编号
  57. } query[MAXQ * ];
  58. int answer[MAXQ];//存储最后的查询结果,下标0~Q-1
  59. int h[MAXQ];
  60. int tt;
  61. int Q;
  62.  
  63. void add_query(int u, int v, int index)
  64. {
  65. query[tt].q = v;
  66. query[tt].next = h[u];
  67. query[tt].index = index;
  68. h[u] = tt++;
  69. query[tt].q = u;
  70. query[tt].next = h[v];
  71. query[tt].index = index;
  72. h[v] = tt++;
  73. }
  74.  
  75. void init()
  76. {
  77. tot = ;
  78. memset(head, -, sizeof(head));
  79. tt = ;
  80. memset(h, -, sizeof(h));
  81. memset(vis, false, sizeof(vis));
  82. memset(F, -, sizeof(F));
  83. memset(ancestor, , sizeof(ancestor));
  84. }
  85.  
  86. void LCA(int u)
  87. {
  88. ancestor[u] = u;
  89. vis[u] = true;
  90. for (int i = head[u]; i != -; i = edge[i].next)
  91. {
  92. int v = edge[i].to;
  93. if (vis[v])
  94. {
  95. continue;
  96. }
  97. LCA(v);
  98. bing(u, v);
  99. ancestor[find(u)] = u;
  100. }
  101. for (int i = h[u]; i != -; i = query[i].next)
  102. {
  103. int v = query[i].q;
  104. if (vis[v])
  105. {
  106. answer[query[i].index] = ancestor[find(v)];
  107. }
  108. }
  109. }
  110.  
  111. bool flag[MAXN];
  112. int Count_num[MAXN];
  113. int main()
  114. {
  115. //freopen("in.txt","r",stdin);
  116. //freopen("out.txt","w",stdout);
  117. int n;
  118. int u, v, k;
  119. while (scanf("%d", &n) == )
  120. {
  121. init();
  122. memset(flag, false, sizeof(flag));
  123. for (int i = ; i <= n; i++)
  124. {
  125. u = readint();
  126. k = readint();
  127. while (k--)
  128. {
  129. v = readint();
  130. flag[v] = true;
  131. addedge(u, v);
  132. addedge(v, u);
  133. }
  134. }
  135. Q = readint();
  136. for (int i = ; i < Q; i++)
  137. {
  138. u = readint();
  139. v = readint();
  140. add_query(u, v, i);
  141. }
  142. int root;
  143. for (int i = ; i <= n; i++)
  144. if (!flag[i])
  145. {
  146. root = i;
  147. break;
  148. }
  149. LCA(root);
  150. memset(Count_num, , sizeof(Count_num));
  151. for (int i = ; i < Q; i++)
  152. {
  153. Count_num[answer[i]]++;
  154. }
  155. for (int i = ; i <= n; i++)
  156. if (Count_num[i] > )
  157. {
  158. printf("%d:%d\n", i, Count_num[i]);
  159. }
  160. }
  161. return ;
  162. }

POJ 1330

HDU 4547

SPOJ 10628  在线第K大点(主席树+LCA)

  1. /*SPOJ 10628
  2. 第一行两个整数N,M 1E5
  3. 第二行有N个整数,其中第i个整数表示点i的权值
  4. 后面N-1行每行两个整数(x,y),表示点x到点y有一条边
  5. 最后M行每行两个整数(u,v,k),表示一组询问*/
  6. /*Huyyt*/
  7. #include<bits/stdc++.h>
  8. #define inf 0x7fffffff
  9. #define ll long long
  10. #define N 100005
  11. #define M 2000005
  12. using namespace std;
  13. inline ll read()
  14. {
  15. ll x=,f=;char ch=getchar();
  16. while(ch>''||ch<''){if(ch=='-')f=-;ch=getchar();}
  17. while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
  18. return x*f;
  19. }
  20. int n,m,tot,sz,cnt,ind,last;
  21. int num[N],pos[N];
  22. int v[N],tmp[N],hash[N],root[N];
  23. int ls[M],rs[M],sum[M];
  24. int deep[N],fa[N][];
  25. struct data{int to,next;}e[];int head[N];
  26. void ins(int u,int v)
  27. {e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;}
  28. void insert(int u,int v)
  29. {ins(u,v);ins(v,u);}
  30. int find(int x)
  31. {
  32. int l=,r=tot;
  33. while(l<=r)
  34. {
  35. int mid=(l+r)>>;
  36. if(hash[mid]<x)l=mid+;
  37. else if(hash[mid]==x)return mid;
  38. else r=mid-;
  39. }
  40. }
  41. void dfs(int x)
  42. {
  43. ind++;num[ind]=x;pos[x]=ind;
  44. for(int i=;i<=;i++)
  45. if((<<i)<=deep[x])fa[x][i]=fa[fa[x][i-]][i-];
  46. else break;
  47. for(int i=head[x];i;i=e[i].next)
  48. if(fa[x][]!=e[i].to)
  49. {
  50. deep[e[i].to]=deep[x]+;
  51. fa[e[i].to][]=x;
  52. dfs(e[i].to);
  53. }
  54. }
  55. int lca(int x,int y)
  56. {
  57. if(deep[x]<deep[y])swap(x,y);
  58. int t=deep[x]-deep[y];
  59. for(int i=;i<=;i++)
  60. if((<<i)&t)x=fa[x][i];
  61. for(int i=;i>=;i--)
  62. if(fa[x][i]!=fa[y][i])
  63. x=fa[x][i],y=fa[y][i];
  64. if(x==y)return x;
  65. return fa[x][];
  66. }
  67. void update(int l,int r,int x,int &y,int num)
  68. {
  69. y=++sz;
  70. sum[y]=sum[x]+;
  71. if(l==r)return;
  72. ls[y]=ls[x];rs[y]=rs[x];
  73. int mid=(l+r)>>;
  74. if(num<=mid)
  75. update(l,mid,ls[x],ls[y],num);
  76. else update(mid+,r,rs[x],rs[y],num);
  77. }
  78. int que(int x,int y,int rk)
  79. {
  80. int a=x,b=y,c=lca(x,y),d=fa[c][];
  81. a=root[pos[a]],b=root[pos[b]],c=root[pos[c]],d=root[pos[d]];
  82. int l=,r=tot;
  83. while(l<r)
  84. {
  85. int mid=(l+r)>>;
  86. int tmp=sum[ls[a]]+sum[ls[b]]-sum[ls[c]]-sum[ls[d]];
  87. if(tmp>=rk)r=mid,a=ls[a],b=ls[b],c=ls[c],d=ls[d];
  88. else rk-=tmp,l=mid+,a=rs[a],b=rs[b],c=rs[c],d=rs[d];
  89. }
  90. return hash[l];
  91. }
  92. int main()
  93. {
  94. n=read(),m=read();
  95. for(int i=;i<=n;i++)
  96. v[i]=read(),tmp[i]=v[i];
  97. sort(tmp+,tmp+n+);
  98. hash[++tot]=tmp[];
  99. for(int i=;i<=n;i++)
  100. if(tmp[i]!=tmp[i-])hash[++tot]=tmp[i];
  101. for(int i=;i<=n;i++)v[i]=find(v[i]);
  102. for(int i=;i<n;i++)
  103. {
  104. int u=read(),v=read();
  105. insert(u,v);
  106. }
  107. dfs();
  108. for(int i=;i<=n;i++)
  109. {
  110. int t=num[i];
  111. update(,tot,root[pos[fa[t][]]],root[i],v[t]);
  112. }
  113. for(int i=;i<=m;i++)
  114. {
  115. int x=read(),y=read(),rk=read();
  116. x^=last;
  117. last=que(x,y,rk);
  118. printf("%d",last);
  119. if(i!=m)printf("\n");
  120. }
  121. return ;
  122. }

HDU 3078  离线修改第K大点

0 a b 表示把点a的权改为b

k a b 表示求出从a到b的路径中,第K大的点权

①Tarjan

  1. /*
  2. 先用离线Tarjan把每个Query树链的LCA求出来
  3. LCA中对连接树Dfs的时候,令p[v]=u,记录v的前驱
  4. LCA结束后,对于每个Query:
  5. 从u开始回溯到LCA,记录值。从v开始回溯到LCA,记录值
  6. 再加上LCA这个点的值,形成一条完整树链。特判树链长度是否小于K
  7. 对树链中的值,从大到小排序,取第K大即可
  8. */
  9. /*Huyyt*/
  10. #include<bits/stdc++.h>
  11. using namespace std;
  12. #define maxn 80005
  13. int head[maxn],qhead[maxn],lag[maxn],kth[maxn],tot1,tot2,f[maxn],vis[maxn],ancestor[maxn],p[maxn];
  14. bool cmp(int a,int b) {return a>b;}
  15. struct Edge
  16. {
  17. int to,next;
  18. }e[maxn*];
  19. struct Query
  20. {
  21. int from,to,next,idx;
  22. }q[maxn*];
  23. void addedge(int u,int v)
  24. {
  25. e[tot1].to=v;
  26. e[tot1].next=head[u];
  27. head[u]=tot1++;
  28. }
  29. void addquery(int u,int v,int idx)
  30. {
  31. q[tot2].from=u;
  32. q[tot2].to=v;
  33. q[tot2].next=qhead[u];
  34. q[tot2].idx=idx;
  35. qhead[u]=tot2++;
  36. }
  37. int find(int x) {return x!=f[x]?f[x]=find(f[x]):x;}
  38. void Union(int u,int v)
  39. {
  40. u=find(u),v=find(v);
  41. if(u!=v) f[v]=u;
  42. }
  43. void LCA(int u)
  44. {
  45. vis[u]=true;
  46. f[u]=u;
  47. for(int i=head[u];i!=-;i=e[i].next)
  48. {
  49. int v=e[i].to;
  50. if(!vis[v])
  51. {
  52. p[v]=u;
  53. LCA(v);
  54. Union(u,v);
  55. }
  56. }
  57. for(int i=qhead[u];i!=-;i=q[i].next)
  58. {
  59. int v=q[i].to;
  60. if(vis[v]) ancestor[q[i].idx]=find(v);
  61. //or storage e[i].lca=e[i^1].lca=find(v)
  62. }
  63. }
  64. int main()
  65. {
  66. //freopen("in.txt","r",stdin);
  67. int T,n,m,u,v,c,cmd;
  68. scanf("%d%d",&n,&m);
  69. tot1=tot2=;
  70. memset(head,-,sizeof(head));
  71. memset(qhead,-,sizeof(qhead));
  72. memset(vis,,sizeof(vis));
  73. for(int i=;i<=n;i++) scanf("%d",&lag[i]);
  74. for(int i=; i<n-; i++)
  75. {
  76. scanf("%d%d",&u,&v);
  77. addedge(u,v);
  78. addedge(v,u);
  79. }
  80. for(int i=; i<m; i++)
  81. {
  82. scanf("%d%d%d",&cmd,&u,&v);
  83. if(cmd==) lag[u]=v;
  84. else
  85. {
  86. addquery(u,v,i);
  87. addquery(v,u,i);
  88. kth[i]=cmd;
  89. }
  90. }
  91. LCA();
  92. for(int i=; i<tot2; i=i+)
  93. {
  94. int u=q[i].from,v=q[i].to,idx=q[i].idx;
  95. int ed=ancestor[idx];
  96. vector<int> chain;
  97. while(u!=ed) chain.push_back(lag[u]),u=p[u];
  98. while(v!=ed) chain.push_back(lag[v]),v=p[v];
  99. chain.push_back(lag[ed]);
  100. if(chain.size()<kth[idx]) {printf("invalid request!\n");continue;}
  101. else
  102. {
  103. sort(chain.begin(),chain.end(),cmp);
  104. printf("%d\n",chain[kth[idx]-]);
  105. }
  106. }
  107. }

②ST

  1. /*Huyyt*/
  2. #include<bits/stdc++.h>
  3. using namespace std;
  4. const int maxn=;
  5. int pre[maxn],E[maxn*],dep[maxn*],pos[maxn],vis[maxn];
  6. int d[maxn*][],val[maxn],num,path[maxn];
  7. int N,Q;
  8. vector<int> g[maxn];
  9.  
  10. void init()
  11. {
  12. for(int i=;i<=N;i++)g[i].clear();
  13. num=;
  14. memset(pos,-,sizeof(pos));
  15. memset(vis,,sizeof(vis));
  16. }
  17.  
  18. void dfs(int u,int depth)
  19. {
  20. E[++num]=u,dep[num]=depth;
  21. if(pos[u]==-)pos[u]=num;
  22. vis[u]=;
  23. int len=g[u].size();
  24. for(int i=;i<len;i++)
  25. {
  26. int v=g[u][i];
  27. if(vis[v])continue;
  28. pre[v]=u;
  29. dfs(v,depth+);
  30. E[++num]=u,dep[num]=depth;
  31. }
  32. }
  33.  
  34. void initRMQ(int n)
  35. {
  36. for(int i=;i<=n;i++)d[i][]=i;
  37. for(int j=;(<<j)<=n;j++)
  38. for(int i=;i+(<<j)<=n;i++)
  39. {
  40. int x=d[i][j-],y=d[i+(<<(j-))][j-];
  41. if(dep[x]<dep[y])d[i][j]=x;
  42. else d[i][j]=y;
  43. }
  44. }
  45.  
  46. int LCA(int u,int v)
  47. {
  48. int x=pos[u],y=pos[v];
  49. if(x>y)swap(x,y);
  50. int k=;
  51. while((<<(k+))<=y-x+)k++;
  52. int a=d[x][k],b=d[y-(<<k)+][k];
  53. if(dep[a]<dep[b])return E[a];
  54. else return E[b];
  55. }
  56.  
  57. void solve(int k,int u,int v)
  58. {
  59. int fa=LCA(u,v);
  60. int cnt=;
  61. while(u!=fa){path[cnt++]=val[u];u=pre[u];}
  62. while(v!=fa){path[cnt++]=val[v];v=pre[v];}
  63. path[cnt++]=val[fa];
  64. sort(path,path+cnt,greater<int>());
  65. if(cnt<k)printf("invalid request!\n");
  66. else printf("%d\n",path[k-]);
  67. }
  68.  
  69. int main()
  70. {
  71. while(scanf("%d%d",&N,&Q)!=EOF)
  72. {
  73. for(int i=;i<=N;i++)scanf("%d",&val[i]);
  74. init();
  75. for(int i=;i<N;i++)
  76. {
  77. int u,v;
  78. scanf("%d%d",&u,&v);
  79. g[u].push_back(v);
  80. g[v].push_back(u);
  81. }
  82. dfs(,);
  83. initRMQ(num);
  84. while(Q--)
  85. {
  86. int k,a,b;
  87. scanf("%d%d%d",&k,&a,&b);
  88. if(!k)val[a]=b;
  89. else solve(k,a,b);
  90. }
  91. }
  92. return ;
  93. }
  1. /*Huyyt*/
  2. #include<bits/stdc++.h>
  3. using namespace std;
  4. #define N 80010
  5. int __pow[];
  6. int fa[N],val[N],p[N];
  7. int node[*N],first[N],dep[*N],dp[*N][];
  8. bool vis[N];
  9. vector<int>e[N];
  10.  
  11. void dfs(int &index , int u ,int d , int par)
  12. {
  13. ++index; vis[u] = true;
  14. first[u] = index; node[index] = u; dep[index] = d; fa[u] = par;
  15. for(int i=; i<e[u].size(); i++)
  16. if(!vis[e[u][i]])
  17. {
  18. dfs(index , e[u][i] , d+ , u);
  19. ++index;
  20. node[index] = u; dep[index] = d;
  21. }
  22. }
  23.  
  24. void ST(int n)
  25. {
  26. int K = (int)(log((double)n) / log(2.0));
  27. for(int i=; i<=n; i++) dp[i][] = i;
  28. for(int j=; j<=K; j++)
  29. for(int i=; i+__pow[j]- <= n ; i++)
  30. {
  31. int a = dp[i][j-];
  32. int b = dp[i+__pow[j-]][j-];
  33. if(dep[a] < dep[b]) dp[i][j] = a;
  34. else dp[i][j] = b;
  35. }
  36. }
  37.  
  38. int RMQ(int x ,int y)
  39. {
  40. int K = (int)(log((double)(y-x+)) / log(2.0));
  41. int a = dp[x][K];
  42. int b = dp[y-__pow[K]+][K];
  43. if(dep[a] < dep[b]) return a;
  44. else return b;
  45. }
  46.  
  47. int LCA(int u ,int v)
  48. {
  49. int x = first[u];
  50. int y = first[v];
  51. if(x > y) swap(x,y);
  52. int index = RMQ(x,y);
  53. return node[index];
  54. }
  55.  
  56. bool cmp(int a, int b)
  57. {
  58. return a > b;
  59. }
  60.  
  61. void path(int &index , int s , int t)
  62. {
  63. while(s != t)
  64. {
  65. p[index++] = val[s];
  66. s = fa[s];
  67. }
  68. p[index++] = val[t];
  69. }
  70.  
  71. void solve(int kth , int u,int v)
  72. {
  73. int lca = LCA(u,v);
  74. int tot = ;
  75. path(tot,u,lca);
  76. path(tot,v,lca);
  77. tot--;
  78. if(kth > tot)
  79. {
  80. printf("invalid request!\n");
  81. return ;
  82. }
  83. sort(p,p+tot,cmp);
  84. printf("%d\n",p[kth-]);
  85. }
  86.  
  87. int main()
  88. {
  89. for(int i=; i<; i++) __pow[i] = << i;
  90.  
  91. int n,q;
  92. scanf("%d%d",&n,&q);
  93. for(int i=; i<=n; i++) scanf("%d",&val[i]);
  94. for(int i=; i<n; i++)
  95. {
  96. int u,v;
  97. scanf("%d%d",&u,&v);
  98. e[u].push_back(v);
  99. e[v].push_back(u);
  100. }
  101.  
  102. int tot = ;
  103. memset(vis,false,sizeof(vis));
  104. dfs(tot,,,-);
  105.  
  106. ST(tot);
  107. while(q--)
  108. {
  109. int op;
  110. scanf("%d",&op);
  111. if(op == )
  112. {
  113. int x,w;
  114. scanf("%d%d",&x,&w);
  115. val[x] = w;
  116. }
  117. else
  118. {
  119. int u,v;
  120. scanf("%d%d",&u,&v);
  121. solve(op,u,v);
  122. }
  123. }
  124. return ;
  125. }

Codeforces 932D  倍增维护

给你一个有根树根的下标为1 每个节点有一个权值 根的权值为0 总共有4e5次 强制在线操作

操作1:在R节点下面加一个权值为W的新节点

操作2:询问从R开始朝根节点走 走到第一个权值不小于它的节点且经过的节点权值和不大于W的最长长度

维护两个数组 一个是father[i][j]表示在i之上 第2^j个比i权值大的点 第二个是sum[i][j]表示从i到第2^j个比i权值大的点途中经过点的权值和(不包括W[i])

  1. /*Huyyt*/
  2. #include<bits/stdc++.h>
  3. #define mem(a,b) memset(a,b,sizeof(a))
  4. #define pb push_back
  5. using namespace std;
  6. typedef long long ll;
  7. typedef unsigned long long ull;
  8. const ll LLmaxn = 2e18;
  9. const int maxn = ;
  10. inline long long read()
  11. {
  12. char c = getchar();
  13. long long ans = ;
  14. while (c < '' || c > '')
  15. {
  16. c = getchar();
  17. }
  18. while (c >= '' && c <= '')
  19. {
  20. ans = ans * + c - '', c = getchar();
  21. }
  22. return ans;
  23. }
  24. ll w[maxn];
  25. ll father[maxn][];
  26. ll sum[maxn][];
  27. int cnt = ;
  28. ll last = ;
  29. void add(ll a, ll b)
  30. {
  31. w[++cnt] = b;
  32. if (w[a] >= w[cnt])
  33. {
  34. father[cnt][] = a;
  35. }
  36. else
  37. {
  38. for (int i = ; i >= ; i--)
  39. {
  40. if (w[father[a][i]] < w[cnt])
  41. {
  42. a = father[a][i];
  43. }
  44. }
  45. father[cnt][] = father[a][];
  46. }
  47. if (father[cnt][] == )
  48. {
  49. sum[cnt][] = LLmaxn;
  50. }
  51. else
  52. {
  53. sum[cnt][] = w[father[cnt][]];
  54. }
  55. for (int i = ; i <= ; i++)
  56. {
  57. father[cnt][i] = father[father[cnt][i - ]][i - ];
  58. if (father[cnt][i] == )
  59. {
  60. sum[cnt][i] = LLmaxn;
  61. }
  62. else
  63. {
  64. sum[cnt][i] = sum[cnt][i - ] + sum[father[cnt][i - ]][i - ];
  65. }
  66. }
  67. }
  68. ll query(ll a, ll b)
  69. {
  70. if (w[a] > b)
  71. {
  72. return ;
  73. }
  74. b -= w[a];
  75. ll ans = ;
  76. for (int i = ; i >= ; i--)
  77. {
  78. if (b >= sum[a][i])
  79. {
  80. b -= sum[a][i];
  81. ans += (1LL << i);
  82. a = father[a][i];
  83. }
  84. }
  85. return ans;
  86. }
  87. void init()
  88. {
  89. w[] = LLmaxn;
  90. w[] = ;
  91. father[][] = ;
  92. mem(sum[], 0x3f);
  93. }
  94. ll a, b;
  95. int main()
  96. {
  97. //cout<<LLmaxn<<endl;
  98. init();
  99. int n, Q;
  100. int ch;
  101. n = read();
  102. for (int i = ; i <= n; i++)
  103. {
  104. ch = read();
  105. a = read();
  106. b = read();
  107. a ^= last;
  108. b ^= last;
  109. if (ch == )
  110. {
  111. add(a, b);
  112. }
  113. else
  114. {
  115. last = query(a, b);
  116. cout << last << endl;
  117. }
  118. }
  119. return ;
  120. }

Codeforces 980E

给你N个点 组成的一颗树 分别从1标号到N 每个点的粉丝数量为2^i个

要求是选择K个点删除 使得剩下没被删的点保持连通且剩下的粉丝数量最大

一旦某个点被删除则其不能通过且该点的粉丝数量清零

假如做法顺着做 找出需要删除那些点的话 因为要保证连通性所以删除一个点需要删除掉他所有子树的点 不好做

题目提示你K<N 所以点N是一定可以保留的 就以N为根倍增预处理祖先 倒着做 找出不需要删除的点即可

  1. /* Huyyt */
  2. #include <bits/stdc++.h>
  3. #define mem(a,b) memset(a,b,sizeof(a))
  4. #define mkp(a,b) make_pair(a,b)
  5. #define pb push_back
  6. using namespace std;
  7. typedef long long ll;
  8. const long long mod = 1e9 + ;
  9. const int N = 1e6 + ;
  10. inline int readint()
  11. {
  12. char c = getchar();
  13. int ans = ;
  14. while (c < '' || c > '')
  15. {
  16. c = getchar();
  17. }
  18. while (c >= '' && c <= '')
  19. {
  20. ans = ans * + c - '', c = getchar();
  21. }
  22. return ans;
  23. }
  24. vector<int> tree[N];
  25. bool check[N];
  26. int father[N][];
  27. int deep[N];
  28. void dfs(int x, int level)
  29. {
  30. for (int i = ; father[father[x][i]][i]; i++)
  31. {
  32. father[x][i + ] = father[father[x][i]][i];
  33. }
  34. deep[x] = level;
  35. for (int i = ; i < tree[x].size(); i++)
  36. {
  37. int to = tree[x][i];
  38. if (to == father[x][])
  39. {
  40. continue;
  41. }
  42. father[to][] = x;
  43. dfs(to, level + );
  44. }
  45. }
  46. int main()
  47. {
  48. int n, k;
  49. n = readint(), k = readint();
  50. int u, v;
  51. for (int i = ; i < n; i++)
  52. {
  53. u = readint(),v = readint();
  54. tree[u].pb(v);
  55. tree[v].pb(u);
  56. }
  57. k = n - k;
  58. k--, check[n] = ;
  59. dfs(n, );
  60. for (int i = n - ; i >= && k; i--)
  61. {
  62. int aim = -;
  63. int now = i;
  64. if (check[i])
  65. {
  66. continue;
  67. }
  68. for (int j = ; j >= ; j--)
  69. {
  70. if (father[now][j] == || check[father[now][j]])
  71. {
  72. continue;
  73. }
  74. now = father[now][j];
  75. }
  76. if (deep[i] - deep[now] + <= k)
  77. {
  78. now = i;
  79. while (now != && !check[now])
  80. {
  81. check[now] = ;
  82. k--;
  83. now = father[now][];
  84. }
  85. }
  86. }
  87. for (int i = ; i <= n - ; i++)
  88. {
  89. if (!check[i])
  90. {
  91. cout << i << " ";
  92. }
  93. }
  94. return ;
  95. }

LCA统计的更多相关文章

  1. 【BZOJ-3910】火车 倍增LCA + 并查集

    3910: 火车 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 262  Solved: 90[Submit][Status][Discuss] De ...

  2. 洛谷八月月赛Round1凄惨记

    个人背景: 上午9:30放学,然后因为学校举办读书工程跟同学去书城选书,中午回来开始打比赛,下午又回老家,中间抽出一点时间调代码,回家已经8:50了 也许是7月月赛时“连蒙带骗”AK的太幸运然而因同学 ...

  3. UOJ261 【NOIP2016】天天爱跑步

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...

  4. BZOJ4719 [Noip2016]天天爱跑步

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...

  5. UOJ#400. 【CTSC2018】暴力写挂

    传送门 看到要求两棵树的 \(lca\) 深度不太好操作 考虑枚举第二棵树的 \(lca\),这样剩下的都是只和第一棵树有关的 而注意到 \(dis(x,y)=d(x)+d(y)-2d(lca(x,y ...

  6. JZOJ.5305【NOIP2017模拟8.18】C

    Description

  7. BZOJ4543 [POI2014]Hotel加强版

    题意 有一个树形结构,每条边的长度相同,任意两个节点可以相互到达.选3个点.两两距离相等.有多少种方案? 数据范围:n<=100000 分析 参照小蒟蒻yyb的博客. 我们先考虑一个\(O(n^ ...

  8. CODEVS——T 1036 商务旅行

    http://codevs.cn/problem/1036/  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解       题目描述 Descript ...

  9. 0917CSP-S模拟测试赛后总结

    机房搬家后的首战,便是失利. 依旧是挂掉了.这次状态有大问题. 然而状态的问题归根结底还是实力不行. 大约一个小时左右我拿到了T1的部分分.赛时判断了一下大概是高分. (不过赛后发现确实不算什么太高的 ...

随机推荐

  1. java:Springmvc框架1(基本配置,注解配置,转换器引入)

    1.springmvc01:(基本配置) web.xml: <?xml version="1.0" encoding="UTF-8"?> <w ...

  2. 深入理解.NET Core的基元(二)

    原文:Deep-dive into .NET Core primitives, part 2: the shared framework作者:Nate McMaster译文:深入理解.NET Core ...

  3. AJAX中同步和异步的区别和使用场景

    一.简介Ajax请求最重要的问题是代码执行的顺序.最长遇到的问题是,我们定义一个变量接收ajax异步请求的返回结果,后续代码使用,然而后续代码在使用时该变量为初始值,始终得不到想要的结果!!!二.示例 ...

  4. C++中sort函数使用方法

    一.sort函数 1.sort函数包含在头文件为#include<algorithm>的c++标准库中,调用标准库里的排序方法可以实现对数据的排序,但是sort函数是如何实现的,我们不用考 ...

  5. cocos2dx基础篇(1) Cocos2D-X项目创建

    已经入行工作半年多时间了,以前都是把这些东西记录在有道云上面的,现在抽出些时间把以前的笔记腾过来. 具体的环境配置就不用说了,因为现在已经是2018年,只需要下载对应版本解压后就能使用,不用再像多年前 ...

  6. LeetCode.949-给定数字的最大时间(Largest Time for Given Digits)

    这是悦乐书的第363次更新,第391篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第225题(顺位题号是949).给定4个整数组成的数组,返回最大的24小时时间. 最小的 ...

  7. H3C版本升级

    H3C S5500和S3100都可以通过TFTP方式进行升级,1.设置交换机的vlan1的ip地址,如10.10.10.2/242.设置电脑和交换机连接的ip地址,如10.10.10.1/243.在交 ...

  8. JWT的实现原理

    前言最近在做一个python项目的改造,将python项目重构为java项目,过程中遇到了这个知识点,觉得这个蛮实用的,所以下班后回来趁热打铁写下这篇总结,希望后面的人能够有所借鉴,少走弯路. 一.优 ...

  9. 【嵌入式开发】Raspberry Pi 树莓派性能测试

    Raspberry Pi 树莓派性能测试 目录: CPU Linpack基准测试 源码 编译/运行 结果 Whetstone/Dhrystone综合基准测试 源码 编译/运行 结果 OpenSSL安全 ...

  10. IDEA 如何批量修改变量名

    修改前的变量 System.out.println("bbbbb"); System.out.println("bbbbb"); System.out.prin ...