http://172.20.6.3/Problem_Show.asp?id=1454

从这道题我充分认识到我的脑子里好多水orz。

如果知道了这个要用二分和差分写,就没什么思考上的难点了(屁咧你写了一个下午)。

下面讲述一下我写这道题的辛酸历程:

我最开始写了个树链剖分+线段树+二分+差分数组,tle了一个点,这完全搞不懂啊,什么鬼啊,为什么啊,不然你告诉我怎么写啊。

然后我去找了a了此题的Lcentury大神,然后他告诉我:“这个题要用tarjan求lca啊,都什么年代了还用树链剖分,tanjan快啊,你这肯定要超时的。”然后我就信了Lcentury大神的邪学了一波tanjan。

我还很奇怪,tanjan怎么求两点之间距离啊???等到我辛辛苦苦读了一遍tanjan求两点距离的写法之后,狂喷凌霄血,原来只要找到lca一减就出来了,所以说树链剖分找lca是不会tle的,tle是因为我多加了一个sb线段树。

所以我两种都写了一遍[二哈],事实证明两种方案速度的确没有差很多。。。大数据一个是2609ms一个是2640ms。

下面展示我的两个代码(mdzz),就当mark模板了。

tanjan

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #include<cmath>
  5. #include<iostream>
  6. using namespace std;
  7. #define lc x*2
  8. #define rc x*2+1
  9. const int maxn=;
  10. int n,m;
  11. struct nod{
  12. int next,y,v;
  13. }e[maxn*];
  14. int head[maxn]={},tot=;
  15. struct wtf{
  16. int x,y,fa,v;
  17. }a[maxn];
  18. struct node{
  19. int y,id,next;
  20. }d[maxn*];
  21. int lin[maxn]={};
  22. int fa[maxn]={};
  23. int f[maxn]={};
  24. int cnt,ned;
  25. int vis[maxn]={};
  26. int dis[maxn]={};
  27. inline void init(int x,int y,int v){
  28. e[++tot].y=y;
  29. e[tot].v=v;
  30. e[tot].next=head[x];
  31. head[x]=tot;
  32. }
  33.  
  34. inline void insert(int x,int y,int id){
  35. d[++tot].y=y;
  36. d[tot].id=id;
  37. d[tot].next=lin[x];
  38. lin[x]=tot;
  39. }
  40. int read(){
  41. char ch=getchar();int x=,f=;
  42. while(ch>''||ch<''){if(ch=='-')f=-;ch=getchar();}
  43. while(ch<=''&&ch>=''){x*=;x+=ch-'';ch=getchar();}
  44. return x*f;
  45. }
  46. int find(int x){
  47. if(f[x]==-)
  48. return x;
  49. return f[x]=find(f[x]);
  50. }
  51. void merge(int u,int v){
  52. int x=find(u);
  53. int y=find(v);
  54. if(x!=y) f[x]=y;
  55. }
  56. void tarj(int x){
  57. int y,v;
  58. fa[x]=x;
  59. vis[x]=;
  60. for(int i=head[x];i;i=e[i].next){
  61. y=e[i].y;v=e[i].v;
  62. if(vis[y])continue;
  63. dis[y]=dis[x]+v;
  64. tarj(y);
  65. merge(x,y);
  66. fa[find(x)]=x;
  67. }
  68. for(int i=lin[x];i;i=d[i].next){
  69. y=d[i].y;
  70. if(vis[y])
  71. a[d[i].id].fa=fa[find(y)];
  72. }
  73. }
  74. bool mmp(wtf aa,wtf bb){
  75. return aa.v>bb.v;
  76. }
  77. void dfs3(int x,int pa,int val){
  78. int y,v;
  79. for(int i=head[x];i;i=e[i].next){
  80. y=e[i].y;v=e[i].v;
  81. if(y==pa)continue;
  82. dfs3(y,x,v);
  83. vis[x]+=vis[y];
  84. }
  85. // cout<<ned<<vis[x]<<val<<x<<endl;
  86. if(vis[x]==ned)cnt=max(cnt,val);
  87. }
  88. inline bool check(int x){
  89. cnt=;
  90. memset(vis,,sizeof(vis));
  91. for(int i=;i<=m;i++){
  92. if(a[i].v>x){
  93. vis[a[i].x]++;
  94. vis[a[i].y]++;
  95. vis[a[i].fa]-=;
  96. }
  97. else{
  98. ned=i-;
  99. break;
  100. }
  101. if(i==m)ned=m;
  102. }
  103. dfs3(,,);
  104. if(a[].v-cnt<=x)return ;
  105. else return ;
  106. }
  107. inline int doit(){
  108. int l=,r=a[].v;
  109. while(l<r){
  110. int mid=(l+r)/;
  111. if(check(mid))r=mid;
  112. else l=mid+;
  113. }
  114. return l;
  115. }
  116. int main(){
  117. //freopen("wtf.in","r",stdin);
  118. int size=<<;
  119. char *p=(char*)malloc(size)+size;
  120. __asm__("movl %0,%%esp\n"::"r"(p));
  121. n=read();m=read();
  122. int x,y,v;
  123. for(int i=;i<n;i++){
  124. x=read();y=read();v=read();
  125. init(x,y,v);init(y,x,v);
  126. }tot=;
  127. for(int i=;i<=m;i++){
  128. a[i].x=read();a[i].y=read();
  129. insert(a[i].x,a[i].y,i);
  130. insert(a[i].y,a[i].x,i);
  131. }memset(f,-,sizeof(f));
  132. tarj();
  133. for(int i=;i<=m;i++){
  134. a[i].v=dis[a[i].x]+dis[a[i].y]-dis[a[i].fa]*;
  135. }
  136. sort(a+,a++m,mmp);
  137. printf("%d\n",doit());
  138. return ;
  139. }

树链剖分

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #include<cmath>
  5. #include<iostream>
  6. using namespace std;
  7. #define lc x*2
  8. #define rc x*2+1
  9. const int maxn=;
  10. int n,m;
  11. struct nod{
  12. int next,y,v;
  13. }e[maxn*];
  14. int head[maxn]={},tot=;
  15. int dep[maxn]={},fa[maxn]={},kid[maxn]={};
  16. int top[maxn]={};
  17. int dis[maxn]={};
  18. inline void init(int x,int y,int v){
  19. e[++tot].y=y;
  20. e[tot].v=v;
  21. e[tot].next=head[x];
  22. head[x]=tot;
  23. }
  24. int dfs(int x,int pa){
  25. int y,val,v,tsn=,hug=;
  26. dep[x]=dep[pa]+;
  27. fa[x]=pa;
  28. for(int i=head[x];i;i=e[i].next){
  29. y=e[i].y;v=e[i].v;
  30. if(y==pa)continue;
  31. dis[y]=dis[x]+v;
  32. val=dfs(y,x);
  33. if(val>hug)hug=val,kid[x]=y;
  34. tsn+=val;
  35. }
  36. tsn+=;
  37. return tsn;
  38. }
  39. void dfs1(int x,int pa){
  40. int y,v;
  41. top[x]=pa;
  42. if(kid[x])dfs1(kid[x],pa);
  43. for(int i=head[x];i;i=e[i].next){
  44. y=e[i].y;v=e[i].v;
  45. if(y==fa[x]||y==kid[x])continue;
  46. dfs1(y,y);
  47. }
  48. }
  49. int getit(int x,int y){
  50. int xx=top[x],yy=top[y];
  51. while(xx!=yy){
  52. if(dep[xx]<dep[yy]){
  53. swap(xx,yy);
  54. swap(x,y);
  55. }
  56. x=fa[xx];xx=top[x];
  57. }
  58. if(dep[x]>dep[y])return y;
  59. return x;
  60. }
  61. int read(){
  62. char ch=getchar();int x=,f=;
  63. while(ch>''||ch<''){if(ch=='-')f=-;ch=getchar();}
  64. while(ch<=''&&ch>=''){x*=;x+=ch-'';ch=getchar();}
  65. return x*f;
  66. }
  67. struct wtf{
  68. int x,y,fa,v;
  69. }a[maxn];
  70. bool mmp(wtf aa,wtf bb){
  71. return aa.v>bb.v;
  72. }
  73. int cnt,ned;
  74. int vis[maxn]={};
  75. void dfs3(int x,int val){
  76. int y,v;
  77. for(int i=head[x];i;i=e[i].next){
  78. y=e[i].y;v=e[i].v;
  79. if(y==fa[x])continue;
  80. dfs3(y,v);
  81. vis[x]+=vis[y];
  82. }
  83. if(vis[x]==ned)cnt=max(cnt,val);
  84. }
  85. inline bool check(int x){
  86. cnt=;
  87. memset(vis,,sizeof(vis));
  88. for(int i=;i<=m;i++){
  89. if(a[i].v>x){
  90. vis[a[i].x]++;
  91. vis[a[i].y]++;
  92. vis[a[i].fa]-=;
  93. }
  94. else{
  95. ned=i-;
  96. break;
  97. }
  98. if(i==m)ned=m;
  99. }
  100. dfs3(,);
  101. if(a[].v-cnt<=x)return ;
  102. else return ;
  103. }
  104. inline int doit(){
  105. int l=,r=a[].v;
  106. while(l<r){
  107. int mid=(l+r)/;
  108. if(check(mid))r=mid;
  109. else l=mid+;
  110. }
  111. return l;
  112. }
  113. int main(){
  114. //freopen("wtf.in","r",stdin);
  115. int size=<<;
  116. char *p=(char*)malloc(size)+size;
  117. __asm__("movl %0,%%esp\n"::"r"(p));
  118. n=read();m=read();
  119. int x,y,v;
  120. for(int i=;i<n;i++){
  121. x=read();y=read();v=read();
  122. init(x,y,v);init(y,x,v);
  123. }dfs(,);
  124. dfs1(,);
  125. for(int i=;i<=m;i++){
  126. a[i].x=read();a[i].y=read();
  127. a[i].fa=getit(a[i].x,a[i].y);
  128. a[i].v=dis[a[i].x]+dis[a[i].y]-*dis[a[i].fa];
  129. }sort(a+,a++m,mmp);
  130. printf("%d\n",doit());
  131. return ;
  132. }

JZYZOJ1454 NOIP2015 D2T3_运输计划 二分 差分数组 lca tarjan 树链剖分的更多相关文章

  1. loj2425 「NOIP2015」运输计划[二分答案+树上差分]

    看到题意最小化最长路径,显然二分答案,枚举链长度不超过$\text{mid}$,然后尝试检验.````` 检验是否存在这样一个边置为0后,全部链长$\le\text{mid}$,其最终目标就是.要让所 ...

  2. 【洛谷 P4211】[LNOI2014]LCA(树链剖分,差分)

    题目链接 看到题目肯定首先想到要求LCA(其实是我菜),可乍一看,n与q的规模为5W, 求LCA的复杂度为\(O(logN)\),那么总时间复杂度为\(O(nq\ log\ n)\). 怎么搞呢? 会 ...

  3. [BZOJ 3626] [LNOI2014] LCA 【树链剖分 + 离线 + 差分询问】

    题目链接: BZOJ - 3626 题目分析 考虑这样的等价问题,如果我们把一个点 x 到 Root 的路径上每个点的权值赋为 1 ,其余点的权值为 0,那么从 LCA(x, y) 的 Depth 就 ...

  4. HDU 5044 (树链剖分+树状数组+点/边改查)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5044 题目大意:修改链上点,修改链上的边.查询所有点,查询所有边. 解题思路: 2014上海网赛的变 ...

  5. BZOJ_4326_[NOIP2015]_运输计划_(二分+LCA_树链剖分/Tarjan+差分)

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=4326 给出一棵带有边权的树,以及一系列任务,任务是从树上的u点走到v点,代价为u到v路径上的权 ...

  6. Luogu 2680 NOIP 2015 运输计划(树链剖分,LCA,树状数组,树的重心,二分,差分)

    Luogu 2680 NOIP 2015 运输计划(树链剖分,LCA,树状数组,树的重心,二分,差分) Description L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之 ...

  7. NOIP2015 运输计划 - 二分 + 树链剖分 / (倍增 + 差分)

    BZOJ CodeVS Uoj 题目大意: 给一个n个点的边带权树,给定m条链,你可以选择树中的任意一条边,将它置为0,使得最长的链长最短. 题目分析: 最小化最大值,二分. 二分最短长度mid,将图 ...

  8. luogu P2680 运输计划 (二分答案+树上差分)

    题目背景 公元 20442044 年,人类进入了宇宙纪元. 题目描述 公元20442044 年,人类进入了宇宙纪元. L 国有 nn 个星球,还有 n-1n−1 条双向航道,每条航道建立在两个星球之间 ...

  9. 洛谷 P2680 运输计划-二分+树上差分(边权覆盖)

    P2680 运输计划 题目背景 公元 20442044 年,人类进入了宇宙纪元. 题目描述 公元20442044 年,人类进入了宇宙纪元. L 国有 nn 个星球,还有 n-1n−1 条双向航道,每条 ...

随机推荐

  1. Problem B. Harvest of Apples(杭电2018年多校+组合数+逆元+莫队)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6333 题目: 题意:求C(n,0)+C(n,1)+……+C(n,m)的值. 思路:由于t和n数值范围太 ...

  2. HDU 1175 连连看 (深搜+剪枝)

    题目链接 Problem Description "连连看"相信很多人都玩过.没玩过也没关系,下面我给大家介绍一下游戏规则:在一个棋盘中,放了很多的棋子.如果某两个相同的棋子,可以 ...

  3. 集合框架源码学习之LinkedList

    0-1. 简介 0-2. 内部结构分析 0-3. LinkedList源码分析 0-3-1. 构造方法 0-3-2. 添加add方法 0-3-3. 根据位置取数据的方法 0-3-4. 根据对象得到索引 ...

  4. Spark-2.3.2【SparkStreaming+SparkSQL-实时仪表盘应用】

    应用场景:实时仪表盘(即大屏),每个集团下有多个mall,每个mall下包含多家shop,需实时计算集团下各mall及其shop的实时销售分析(区域.业态.店铺TOP.总销售额等指标)并提供可视化展现 ...

  5. Collection包结构,与Collections的区别

    Collection 1.Collection是集合类的顶级接口: 2.实现接口和类主要有Set.List.LinkedList.ArrayList.Vector.Stack.Set: Collect ...

  6. 关于shutdown和close

    示例代码: void str_cli(FILE *fp, int sockfd) { pid_t pid; char sendline[MAXLINE], recvline[MAXLINE]; ) { ...

  7. Bit banging

    Bit banging Bit banging is a technique for serial communications using software instead of dedicated ...

  8. linux dpm机制分析(上)【转】

    转自:http://blog.csdn.net/lixiaojie1012/article/details/23707681 1      DPM介绍 1.1        Dpm:  设备电源管理, ...

  9. 用pyperclip 模块拷贝粘贴字符串

    >>> import pyperclip>>> pyperclip.copy('Hello world!')>>> pyperclip.paste ...

  10. 【bzoj4530】大融合(LCT的子树维护)

    LCT维护子树并没有想象中的那么难,在这里只是复习下. (其他的维护子树的题目,可见:“共价大爷游长沙”) 只要记录下虚边连接的信息就好了. #include<bits/stdc++.h> ...