Distance on the tree

题目链接

https://nanti.jisuanke.com/t/38229

Describe

DSM(Data Structure Master) once learned about tree when he was preparing for NOIP(National Olympiad in Informatics in Provinces) in Senior High School. So when in Data Structure Class in College, he is always absent-minded about what the teacher says.

The experienced and knowledgeable teacher had known about him even before the first class. However, she didn't wish an informatics genius would destroy himself with idleness. After she knew that he was so interested in ACM(ACM International Collegiate Programming Contest), she finally made a plan to teach him to work hard in class, for knowledge is infinite.

This day, the teacher teaches about trees." A tree with nnn nodes, can be defined as a graph with only one connected component and no cycle. So it has exactly n−1 edges..." DSM is nearly asleep until he is questioned by teacher. " I have known you are called Data Structure Master in Graph Theory, so here is a problem. "" A tree with nnn nodes, which is numbered from 1 to n. Edge between each two adjacent vertexes uuu and v has a value w, you're asked to answer the number of edge whose value is no more than k during the path between u and v."" If you can't solve the problem during the break, we will call you DaShaMao(Foolish Idiot) later on."

The problem seems quite easy for DSM. However, it can hardly be solved in a break. It's such a disgrace if DSM can't solve the problem. So during the break, he telephones you just for help. Can you save him for his dignity?

Input

In the first line there are two integers n,m represent the number of vertexes on the tree and queries(\(2≤n≤10^5,1≤m≤10^5\))

The next n-1 lines, each line contains three integers u,v,w indicates there is an undirected edge between nodes uuu and v with value w. (\(1≤u,v≤n,1≤w≤10^9\))

The next mmm lines, each line contains three integers u,v,k be consistent with the problem given by the teacher above. (\(1≤u,v≤n,0≤k≤10^9\))

Output

For each query, just print a single line contains the number of edges which meet the condition.

样例输入1

3 3

1 3 2

2 3 7

1 3 0

1 2 4

1 2 7

样例输出1

0

1

2

样例输入2

5 2

1 2 1000000000

1 3 1000000000

2 4 1000000000

3 5 1000000000

2 3 1000000000

4 5 1000000000

样例输出2

2

4

题意

给你一棵树,问两个点之间边权小与等于k的数量。

题解

方法一:

比赛时,智商不够,靠数据结构来凑,弱弱的我直接树剖,然后用主席树,感觉就是把两个板子结合一下。第一次一遍AC,看了好几遍才确定自己没看错。

过了n天之后,当我刷完了树链剖分专题,并且遇到了一道和此题相似度极高的题目后,

我终于发现了原来我就是个DaShaMao(Foolish Idiot),完全可以不用主席树。

方法二:

可以看 https://www.cnblogs.com/mmmqqdd/p/10799395.html

这里我也讲一下大概思路:我们先将询问按照val(题目中的k)从小到大排序,那么我们扫一遍询问数组,因为val单增,所以对于每个询问i,我们就把权值小于等于val[i]的位置加一。答案就是直接求u到v的路径和。

方法二很好写,我写了25分钟,一遍AC了。

代码1——树链剖分+主席数(在线,不建议使用)

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define ll long long
  4. #define N 100050
  5. #define INF 123456789
  6. int n,m;
  7. int tot,last[N];
  8. ll ans[N];
  9. int cnt,fa[N],dp[N],size[N],son[N],rk[N],kth[N],top[N];
  10. struct Query
  11. {
  12. int l,r,id; ll val;
  13. bool operator <(const Query&b)const
  14. {return val<b.val;}
  15. }a[N],que[N<<1];
  16. struct Edge{int from,to,s;}edges[N<<1];
  17. struct Tree{int l,r;ll sum;}tr[N<<2];
  18. template<typename T>void read(T&x)
  19. {
  20. ll k=0; char c=getchar();
  21. x=0;
  22. while(!isdigit(c)&&c!=EOF)k^=c=='-',c=getchar();
  23. if (c==EOF)exit(0);
  24. while(isdigit(c))x=x*10+c-'0',c=getchar();
  25. x=k?-x:x;
  26. }
  27. void read_char(char &c)
  28. {while(!isalpha(c=getchar())&&c!=EOF);}
  29. void AddEdge(int x,int y)
  30. {
  31. edges[++tot]=Edge{x,y,last[x]};
  32. last[x]=tot;
  33. }
  34. void dfs1(int x,int pre)
  35. {
  36. fa[x]=pre;
  37. dp[x]=dp[pre]+1;
  38. size[x]=1;
  39. son[x]=0;
  40. for(int i=last[x];i;i=edges[i].s)
  41. {
  42. Edge &e=edges[i];
  43. if (e.to==pre)continue;
  44. dfs1(e.to,x);
  45. size[x]+=size[e.to];
  46. if (size[e.to]>size[son[x]])son[x]=e.to;
  47. }
  48. }
  49. void dfs2(int x,int y)
  50. {
  51. rk[x]=++cnt;
  52. kth[cnt]=x;
  53. top[x]=y;
  54. if (son[x]==0)return;
  55. dfs2(son[x],y);
  56. for(int i=last[x];i;i=edges[i].s)
  57. {
  58. Edge &e=edges[i];
  59. if (e.to==fa[x]||e.to==son[x])continue;
  60. dfs2(e.to,e.to);
  61. }
  62. }
  63. void bt(int x,int l,int r)
  64. {
  65. tr[x].l=l; tr[x].r=r; tr[x].sum=0;
  66. if (l==r)return;
  67. int mid=(l+r)>>1;
  68. bt(x<<1,l,mid);
  69. bt(x<<1|1,mid+1,r);
  70. }
  71. void update(int x,int p,ll tt)
  72. {
  73. if (p<=tr[x].l&&tr[x].r<=p)
  74. {
  75. tr[x].sum+=tt;
  76. return;
  77. }
  78. int mid=(tr[x].l+tr[x].r)>>1;
  79. if (p<=mid)update(x<<1,p,tt);
  80. if (mid<p)update(x<<1|1,p,tt);
  81. tr[x].sum=tr[x<<1].sum+tr[x<<1|1].sum;
  82. }
  83. ll query(int x,int l,int r)
  84. {
  85. if (l<=tr[x].l&&tr[x].r<=r)
  86. return tr[x].sum;
  87. int mid=(tr[x].l+tr[x].r)>>1; ll ans=0;
  88. if (l<=mid)ans+=query(x<<1,l,r);
  89. if (mid<r)ans+=query(x<<1|1,l,r);
  90. return ans;
  91. }
  92. ll get_sum(int x,int y)
  93. {
  94. int fx=top[x],fy=top[y];ll ans=0;
  95. while(fx!=fy)
  96. {
  97. if (dp[fx]<dp[fy])swap(x,y),swap(fx,fy);
  98. ans+=query(1,rk[fx],rk[x]);
  99. x=fa[fx]; fx=top[x];
  100. }
  101. if (dp[x]<dp[y])swap(x,y);
  102. ans+=query(1,rk[y],rk[x]);
  103. return ans;
  104. }
  105. void work()
  106. {
  107. read(n); read(m);
  108. for(int i=1;i<=n;i++)read(a[i].val),a[i].id=i;
  109. for(int i=1;i<=n-1;i++)
  110. {
  111. int x,y;
  112. read(x); read(y);
  113. AddEdge(x,y);
  114. AddEdge(y,x);
  115. }
  116. int num=0;
  117. for(int i=1;i<=m;i++)
  118. {
  119. int l,r,x,y;
  120. read(l); read(r); read(x);read(y);
  121. que[++num]=Query{l,r,-i,x-1};
  122. que[++num]=Query{l,r,i,y};
  123. }
  124. sort(a+1,a+n+1);
  125. sort(que+1,que+num+1);
  126. dfs1(1,0);
  127. dfs2(1,1);
  128. bt(1,1,n);
  129. int ds=1;
  130. for(int i=1;i<=num;i++)
  131. {
  132. while(ds<=n&&a[ds].val<=que[i].val)
  133. {
  134. update(1,rk[a[ds].id],a[ds].val);
  135. ds++;
  136. }
  137. ll sum=get_sum(que[i].l,que[i].r);
  138. if (que[i].id<0) ans[-que[i].id]-=sum;
  139. else ans[que[i].id]+=sum;
  140. }
  141. printf("%lld",ans[1]);
  142. for(int i=2;i<=m;i++)printf(" %lld",ans[i]);
  143. printf("\n");
  144. }
  145. void clear()
  146. {
  147. tot=0; cnt=0;
  148. memset(last,0,sizeof(last));
  149. memset(ans,0,sizeof(ans));
  150. }
  151. int main()
  152. {
  153. #ifndef ONLINE_JUDGE
  154. freopen("aa.in","r",stdin);
  155. #endif
  156. while(1)
  157. {
  158. clear();
  159. work();
  160. }
  161. }

代码2--树链剖分+线段树(离线)

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define ll long long
  4. #define N 100050
  5. int n,m,ans[N];
  6. int tot,last[N];
  7. int cnt,fa[N],dp[N],size[N],son[N],rk[N],kth[N],top[N];
  8. struct Tree{int l,r,sum;}tr[N<<2];
  9. struct Edge{int from,to,val,s;}edges[N<<1];
  10. struct Query
  11. {
  12. int id,l,r,val;
  13. bool operator <(const Query&b)const
  14. {return val<b.val;}
  15. }que[N],a[N];
  16. template<typename T>void read(T&x)
  17. {
  18. ll k=0; char c=getchar();
  19. x=0;
  20. while(!isdigit(c)&&c!=EOF)k^=c=='-',c=getchar();
  21. if (c==EOF)exit(0);
  22. while(isdigit(c))x=x*10+c-'0',c=getchar();
  23. x=k?-x:x;
  24. }
  25. void read_char(char &c)
  26. {while(!isalpha(c=getchar())&&c!=EOF);}
  27. void AddEdge(int x,int y,int z)
  28. {
  29. edges[++tot]=Edge{x,y,z,last[x]};
  30. last[x]=tot;
  31. }
  32. void dfs1(int x,int pre)
  33. {
  34. fa[x]=pre;
  35. dp[x]=dp[pre]+1;
  36. size[x]=1;
  37. son[x]=0;
  38. for(int i=last[x];i;i=edges[i].s)
  39. {
  40. Edge &e=edges[i];
  41. if (e.to==pre)continue;
  42. a[e.to].id=e.to;
  43. a[e.to].val=e.val;
  44. dfs1(e.to,x);
  45. size[x]+=size[e.to];
  46. if (size[e.to]>size[son[x]])son[x]=e.to;
  47. }
  48. }
  49. void dfs2(int x,int y)
  50. {
  51. rk[x]=++cnt;
  52. kth[cnt]=x;
  53. top[x]=y;
  54. if (son[x]==0)return;
  55. dfs2(son[x],y);
  56. for(int i=last[x];i;i=edges[i].s)
  57. {
  58. Edge &e=edges[i];
  59. if (e.to==fa[x]||e.to==son[x])continue;
  60. dfs2(e.to,e.to);
  61. }
  62. }
  63. void bt(int x,int l,int r)
  64. {
  65. tr[x].l=l; tr[x].r=r; tr[x].sum=0;
  66. if (l==r)return;
  67. int mid=(l+r)>>1;
  68. bt(x<<1,l,mid);
  69. bt(x<<1|1,mid+1,r);
  70. }
  71. void update(int x,int p)
  72. {
  73. tr[x].sum++;
  74. if (tr[x].l==tr[x].r)return;
  75. int mid=(tr[x].l+tr[x].r)>>1;
  76. if (p<=mid)update(x<<1,p);
  77. else update(x<<1|1,p);
  78. }
  79. int query(int x,int l,int r)
  80. {
  81. if (l<=tr[x].l&&tr[x].r<=r)return tr[x].sum;
  82. int mid=(tr[x].l+tr[x].r)>>1,a1=0,a2=0;
  83. if(l<=mid)a1=query(x<<1,l,r);
  84. if(mid<r)a2=query(x<<1|1,l,r);
  85. return a1+a2;
  86. }
  87. int get_sum(int x,int y)
  88. {
  89. int fx=top[x],fy=top[y],ans=0;
  90. while(fx!=fy)
  91. {
  92. if (dp[fx]<dp[fy])swap(x,y),swap(fx,fy);
  93. ans+=query(1,rk[fx],rk[x]);
  94. x=fa[fx]; fx=top[x];
  95. }
  96. if (dp[x]<dp[y])swap(x,y);
  97. ans+=query(1,rk[y]+1,rk[x]);
  98. return ans;
  99. }
  100. int main()
  101. {
  102. #ifndef ONLINE_JUDGE
  103. freopen("aa.in","r",stdin);
  104. #endif
  105. read(n); read(m);
  106. for(int i=1;i<=n-1;i++)
  107. {
  108. int x,y,z;
  109. read(x); read(y); read(z);
  110. AddEdge(x,y,z);
  111. AddEdge(y,x,z);
  112. }
  113. dfs1(1,0);
  114. dfs2(1,1);
  115. bt(1,1,n);
  116. sort(a+1,a+n+1);
  117. for(int i=1;i<=m;i++)
  118. {
  119. que[i].id=i;
  120. read(que[i].l); read(que[i].r); read(que[i].val);
  121. }
  122. sort(que+1,que+m+1);
  123. int top=1;
  124. for(int i=1;i<=m;i++)
  125. {
  126. while(top<=n&&a[top].val<=que[i].val)
  127. {
  128. update(1,rk[a[top].id]);
  129. top++;
  130. }
  131. ans[que[i].id]=get_sum(que[i].l,que[i].r);
  132. }
  133. for(int i=1;i<=m;i++)printf("%d\n",ans[i]);
  134. }

南昌网络赛J. Distance on the tree 树链剖分的更多相关文章

  1. 2019年ICPC南昌网络赛 J. Distance on the tree 树链剖分+主席树

    边权转点权,每次遍历到下一个点,把走个这条边的权值加入主席树中即可. #include<iostream> #include<algorithm> #include<st ...

  2. 南昌网络赛J. Distance on the tree 树链剖分+主席树

    Distance on the tree 题目链接 https://nanti.jisuanke.com/t/38229 Describe DSM(Data Structure Master) onc ...

  3. 2019南昌网络赛 J Distance on the tree 主席树+lca

    题意 给一颗树,每条边有边权,每次询问\(u\)到\(v\)的路径中有多少边的边权小于等于\(k​\) 分析 在树的每个点上建\(1​\)到\(i​\)的权值线段树,查询的时候同时跑\(u,v,lca ...

  4. 2019南昌邀请赛网络赛:J distance on the tree

    1000ms 262144K   DSM(Data Structure Master) once learned about tree when he was preparing for NOIP(N ...

  5. 计蒜客 2019南昌邀请网络赛J Distance on the tree(主席树)题解

    题意:给出一棵树,给出每条边的权值,现在给出m个询问,要你每次输出u~v的最短路径中,边权 <= k 的边有几条 思路:当时网络赛的时候没学过主席树,现在补上.先树上建主席树,然后把边权交给子节 ...

  6. Hdu 5274 Dylans loves tree (树链剖分模板)

    Hdu 5274 Dylans loves tree (树链剖分模板) 题目传送门 #include <queue> #include <cmath> #include < ...

  7. POJ3237 Tree 树链剖分 边权

    POJ3237 Tree 树链剖分 边权 传送门:http://poj.org/problem?id=3237 题意: n个点的,n-1条边 修改单边边权 将a->b的边权取反 查询a-> ...

  8. 2019南昌邀请赛网络预选赛 J.Distance on the tree(树链剖分)

    传送门 题意: 给出一棵树,每条边都有权值: 给出 m 次询问,每次询问有三个参数 u,v,w ,求节点 u 与节点 v 之间权值 ≤ w 的路径个数: 题解: 昨天再打比赛的时候,中途,凯少和我说, ...

  9. 计蒜客 38229.Distance on the tree-1.树链剖分(边权)+可持久化线段树(区间小于等于k的数的个数)+离散化+离线处理 or 2.树上第k大(主席树)+二分+离散化+在线查询 (The Preliminary Contest for ICPC China Nanchang National Invitational 南昌邀请赛网络赛)

    Distance on the tree DSM(Data Structure Master) once learned about tree when he was preparing for NO ...

随机推荐

  1. 【概率论】3-6:条件分布(Conditional Distributions Part II)

    title: [概率论]3-6:条件分布(Conditional Distributions Part II) categories: Mathematic Probability keywords: ...

  2. 线段树(结构体建法_QAQ)

    线段树(结构体)模板 #include<iostream> #include<cstdio> #include<queue> #include<cstring ...

  3. create-react-app 构建的项目使用代理 proxy

    1. 正常运行 npm run eject (前三个步骤可省略,最好的是按照第四步操作) 2. create-react-app 的版本在低于 2.0 的时候可以在 package.json 增加 p ...

  4. redis之redis-cluster配置

    为什么要用redis-cluster 并发问题 redis官方生成可以达到 10万/每秒,每秒执行10万条命令 假如业务需要每秒100万的命令执行呢? 数据量太大 一台服务器内存正常是16~256G, ...

  5. 常用SQL之日期格式化和查询重复数据

    本文列举一些工作中常用的SQL,以提升工作效率. 1 日期格式化 使用 DATE_FORMAT(get_date, '%Y-%m-%d') 函数进行格式化.其中:get_date 是需要被格式化的字段 ...

  6. JavaWeb_(Mybatis框架)输入和输出参数_五

    系列博文: JavaWeb_(Mybatis框架)JDBC操作数据库和Mybatis框架操作数据库区别_一 传送门 JavaWeb_(Mybatis框架)使用Mybatis对表进行增.删.改.查操作_ ...

  7. Robot Framework(十五) 扩展RobotFramework框架——远程库接口

    4.2远程库接口 远程库接口提供了在运行Robot Framework本身的机器上运行测试库的方法,以及使用除本机支持的Python和Java之外的其他语言实现库的方法.对于测试库,用户远程库看起来与 ...

  8. Java并发指南4:Java中的锁 Lock和synchronized

    Java中的锁机制及Lock类 锁的释放-获取建立的happens before 关系 锁是java并发编程中最重要的同步机制.锁除了让临界区互斥执行外,还可以让释放锁的线程向获取同一个锁的线程发送消 ...

  9. Java排序之归并排序

    Java排序之归并排序 1. 简介 归并排序的算法是将多个有序数据表合并成一个有序数据表.如果参与合并的只有两个有序表,则成为二路合并.对于一个原始的待排序数列,往往可以通过分割的方法来归结为多路合并 ...

  10. 经典算法:n个人围成一圈,报m的离开,最后剩下谁?

    public int remainPersonNumber(int n, int m) { //输入不合法 if(n < 1 || m < 1) return -1; //初始化,存入Li ...