【题目链接】http://acm.hdu.edu.cn/showproblem.php?pid=5893

【题目大意】

  给出一棵树,每条边上都有一个边权,现在有两个操作,操作一要求将x到y路径上所有边更改为c权值,操作二要求查询x到y的路径上有几段连续的权值相同的。

【题解】

  首先由于是边权,所以把所有边的存下来,做一遍剖分,将权值保存在每条边深度较深的点上,作为点权,用区间合并线段树维护区间内的线段段数,沿链修改的时候注意剖分出的区间的起点是不更新的,因为边权变成点权之后链修改的LCA是不修改的。查询的时候由于边权转点权之后点权位置的特殊性,我们每次在查询a到b之间的答案的时候,首先求出两者的LCA,同时求出LCA到a和b之间的第一个点,求分别求出a和b与其第二root之间的答案,再判断一下交接处的情况,就能计算出答案。

【代码】

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. using namespace std;
  5. const int N=1000000;
  6. int tot,x,d[N],num[N],ed=0,u,w,n,m,i,v[N],vis[N],f[N],g[N],nxt[N],size[N],son[N],st[N],en[N],dfn,top[N],t;char ch;
  7. void add(int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
  8. void dfs(int x){
  9. size[x]=1;
  10. for(int i=g[x];i;i=nxt[i])if(v[i]!=f[x]){
  11. f[v[i]]=x,d[v[i]]=d[x]+1;
  12. dfs(v[i]),size[x]+=size[v[i]];
  13. if(size[v[i]]>size[son[x]])son[x]=v[i];
  14. }
  15. }
  16. void dfs2(int x,int y){
  17. if(x==-1)return;
  18. st[x]=++dfn;top[x]=y;
  19. if(son[x])dfs2(son[x],y);
  20. for(int i=g[x];i;i=nxt[i])if(v[i]!=son[x]&&v[i]!=f[x])dfs2(v[i],v[i]);
  21. en[x]=dfn;
  22. }
  23. int T[N<<2],mark[N<<2],cl[N<<2],cr[N<<2],L,R;
  24. void up(int x){
  25. T[x]=T[x<<1]+T[x<<1|1]-(cr[x<<1]==cl[x<<1|1]);
  26. cl[x]=cl[x<<1];
  27. cr[x]=cr[x<<1|1];
  28. }
  29. void pushdown(int x,int l,int r){
  30. if(l==r)return;
  31. if(mark[x]!=-1){
  32. mark[x<<1]=mark[x<<1|1]=mark[x];
  33. cl[x<<1]=cl[x<<1|1]=mark[x];
  34. cr[x<<1]=cr[x<<1|1]=mark[x];
  35. T[x<<1]=T[x<<1|1]=1;
  36. mark[x]=-1;
  37. }
  38. }
  39. void update(int x,int l,int r,int c){
  40. pushdown(x,l,r);
  41. if(L<=l&&r<=R){T[x]=1;mark[x]=cl[x]=cr[x]=c;return;}
  42. int mid=(l+r)/2;
  43. if(L<=mid)update(x<<1,l,mid,c);
  44. if(mid<R)update(x<<1|1,mid+1,r,c);
  45. up(x);
  46. }
  47. void update(int l,int r,int c){
  48. if(l>r)return;
  49. L=l;R=r; update(1,1,n,c);
  50. }
  51. int query(int x,int l,int r){
  52. pushdown(x,l,r);
  53. if(L<=l&&r<=R)return T[x];
  54. int mid=(l+r)/2,ret=0;
  55. if(L<=mid)ret+=query(x<<1,l,mid);
  56. if(mid<R)ret+=query(x<<1|1,mid+1,r);
  57. if(L<=mid&&mid<R)ret-=(cr[x<<1]==cl[x<<1|1]);
  58. return ret;
  59. }
  60. int query(int l,int r){L=l;R=r;return query(1,1,n);}
  61. int color(int x,int l,int r,int f){
  62. if(l==r)return cl[x];
  63. pushdown(x,l,r);
  64. int mid=(l+r)/2;
  65. if(f<=mid)return color(x<<1,l,mid,f);
  66. return color(x<<1|1,mid+1,r,f);
  67. }
  68. int query(int l){return color(1,1,n,l);}
  69. void chain(int x,int y,int c){
  70. for(;top[x]!=top[y];x=f[top[x]]){
  71. if(d[top[x]]<d[top[y]]){int z=x;x=y;y=z;}
  72. update(st[top[x]],st[x],c);
  73. }if(d[x]<d[y]){int z=x;x=y;y=z;}
  74. update(st[y]+1,st[x],c);
  75. }
  76. int find(int x,int y){
  77. int ret=0;
  78. for(;top[x]!=top[y];x=f[top[x]]){
  79. if(d[top[x]]<d[top[y]]){int z=x;x=y;y=z;}
  80. ret+=query(st[top[x]],st[x]);
  81. ret-=(query(st[top[x]])==query(st[f[top[x]]]));
  82. }if(d[x]<d[y]){int z=x;x=y;y=z;}
  83. ret+=query(st[y],st[x]);
  84. return ret;
  85. }
  86. int lca(int x,int y){
  87. for(;top[x]!=top[y];x=f[top[x]])if(d[top[x]]<d[top[y]]){int z=x;x=y;y=z;}
  88. return d[x]<d[y]?x:y;
  89. }
  90. int lca2(int x,int y){
  91. int t;
  92. while(top[x]!=top[y])t=top[y],y=f[top[y]];
  93. return x==y?t:son[x];
  94. }
  95. void init(){
  96. for(int i=0;i<n*4;i++)T[i]=1,mark[i]=-1;
  97. memset(g,dfn=ed=0,sizeof(g));
  98. memset(v,0,sizeof(v));
  99. memset(nxt,0,sizeof(nxt));
  100. memset(son,-1,sizeof(son));
  101. }
  102. int cas;
  103. int e[N][3];
  104. int main(){
  105. while(~scanf("%d%d",&n,&m)){
  106. init();
  107. for(int i=0;i<n-1;i++){
  108. scanf("%d%d%d",&e[i][0],&e[i][1],&e[i][2]);
  109. add(e[i][0],e[i][1]);
  110. add(e[i][1],e[i][0]);
  111. }dfs(1);dfs2(1,1);
  112. for(int i=0;i<n-1;i++){
  113. if(d[e[i][0]]>d[e[i][1]])swap(e[i][0],e[i][1]);
  114. update(st[e[i][1]],st[e[i][1]],e[i][2]);
  115. }char op[10]; int a,b,c;
  116. //for(int i=1;i<=n;i++)printf("%d\n",st[i]);
  117. while(m--){
  118. scanf("%s",op);
  119. scanf("%d%d",&a,&b);
  120. if(op[0]=='Q'){
  121. c=lca(a,b);
  122. int fa=lca2(c,a);
  123. int fb=lca2(c,b);
  124. //printf("%d %d %d\n",c,fa,fb);
  125. //printf("%d %d\n",query(st[fa]),query(st[fb]));
  126. if(a==b)puts("0");
  127. else if(c==a)printf("%d\n",find(b,fb));
  128. else if(c==b)printf("%d\n",find(a,fa));
  129. else printf("%d\n",find(a,fa)+find(b,fb)-(query(st[fa])==query(st[fb])));
  130. }else{
  131. scanf("%d",&c);
  132. chain(a,b,c);
  133. }
  134. }
  135. }return 0;
  136. }

  

HDU 5893 List wants to travel(树链剖分)的更多相关文章

  1. HDU 3966 & POJ 3237 & HYSBZ 2243 树链剖分

    树链剖分是一个很固定的套路 一般用来解决树上两点之间的路径更改与查询 思想是将一棵树分成不想交的几条链 并且由于dfs的顺序性 给每条链上的点或边标的号必定是连着的 那么每两个点之间的路径都可以拆成几 ...

  2. HDU 4897 Little Devil I(树链剖分)(2014 Multi-University Training Contest 4)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4897 Problem Description There is an old country and ...

  3. HDU 5274 Dylans loves tree(树链剖分)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5274 [题目大意] 给出一棵树,每个点有一个权值,权值可修改,且大于等于0,询问链上出现次数为奇数 ...

  4. hdu 3966 Aragorn&#39;s Story(树链剖分+树状数组)

    pid=3966" target="_blank" style="">题目链接:hdu 3966 Aragorn's Story 题目大意:给定 ...

  5. HDU 2460 Network(双连通+树链剖分+线段树)

    HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...

  6. HDU - 3966 Aragorn's Story(树链剖分入门+线段树)

    HDU - 3966 Aragorn's Story Time Limit: 3000MS   Memory Limit: 32768KB   64bit IO Format: %I64d & ...

  7. hdu 3966 Aragorn's Story(树链剖分+树状数组/线段树)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3966 题意: 给出一棵树,并给定各个点权的值,然后有3种操作: I C1 C2 K: 把C1与C2的路 ...

  8. hdu 3966 Aragorn's Story(树链剖分+区间修改+单点查询)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3966 题意:给一棵树,并给定各个点权的值,然后有3种操作: I C1 C2 K: 把C1与C2的路径上 ...

  9. hdu5893 List wants to travel(树链剖分+线段树)

    Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submissi ...

  10. (中等) HDU 5293 Tree chain problem,树链剖分+树形DP。

    Problem Description   Coco has a tree, whose vertices are conveniently labeled by 1,2,…,n.There are ...

随机推荐

  1. windows server 2008 NTP授时服务[转]

    转自  http://www.cnblogs.com/jingdian1956/admin/EditPosts.aspx?opt=1 服务端: 默认情况下,独立服务器WINDOWS SERVER 20 ...

  2. java获得平台相关的行分隔符和java路径分隔符的方法

    System.getProperties(): 行分隔符在windows 下是 \r\n,在Linux下面是 \n, 在Mac下是 \r路径分隔符在windows下是 \ ,在LInux下是 / Sy ...

  3. EditText 默认不获取焦点,弹出软键盘布局变形解决方案

    关于弹出软键盘布局变形解决方案: 在androidMainfest.xml文件中在此Activity中写入 android:windowSoftInputMode="adjustPan&qu ...

  4. hdu 2222 Keywords Search ac自动机模板

    题目链接 先整理一发ac自动机模板.. #include <iostream> #include <vector> #include <cstdio> #inclu ...

  5. Python调用C/C++的种种方法

    Python调用C/C++的种种方法 2010-12-07 09:59 28433人阅读 评论(1) 收藏 Python是解释性语言, 底层就是用c实现的, 所以用python调用C是很容易的, 下面 ...

  6. 转: ES6异步编程: co函数库的含义与用法

    转: ES6异步编程: co函数库的含义与用法 co 函数库是著名程序员 TJ Holowaychuk 于2013年6月发布的一个小工具,用于 Generator 函数的自动执行. 比如,有一个 Ge ...

  7. MFC 可以设置背景色、字体、字体颜色、透明背景的 Static 静态文本控件

    MFC库里没有符合这个条件的控件,于是我自己写了一个,初步测试有效. 注:可以设置透明背景,但还不能做到透明度设置(如50%透明度) 如果设置了背景色,就不保留透明背景 默认背景色是透明的 [cpp] ...

  8. Oracle_用户管理

    创建用户: CREATE USER user   --创建用户user IDENTIFIED {BY password | EXTERNALLY}  --设备用户密码,EXTERNALLY说用该用户由 ...

  9. 修改ubuntu的默认python版本

    ubuntu14.04LTS上装有两个版本的python:python2.7.6与python3.4,默认使用python2.7.6. 可以使用以下命令来修改默认python版本: sudo cp / ...

  10. CodeForces - 61E Enemy is weak

    Description The Romans have attacked again. This time they are much more than the Persians but Shapu ...