经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » 编程经验 » 查看文章
旅行(树链剖分+动态开点线段树)
来源:cnblogs  作者:Fighting_sh  时间:2018/9/25 19:12:25  对本文有异议

旅行

https://www.luogu.org/problemnew/show/P3313

题目描述

S国有N个城市,编号从1到N。城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市。每个城市信仰不同的宗教,如飞天面条神教、隐形独角兽教、绝地教都是常见的信仰。

为了方便,我们用不同的正整数代表各种宗教, S国的居民常常旅行。旅行时他们总会走最短路,并且为了避免麻烦,只在信仰和他们相同的城市留宿。当然旅程的终点也是信仰与他相同的城市。S国政府为每个城市标定了不同的旅行评级,旅行者们常会记下途中(包括起点和终点)留宿过的城市的评级总和或最大值。

在S国的历史上常会发生以下几种事件:

“CC x c“:城市x的居民全体改信了c教;

“CW x w“:城市x的评级调整为w;

“QS x y“:一位旅行者从城市x出发,到城市y,并记下了途中留宿过的城市的评级总和;

“QM x y“:一位旅行者从城市x出发,到城市y,并记下了途中留宿过的城市的评级最大值。

由于年代久远,旅行者记下的数字已经遗失了,但记录开始之前每座城市的信仰与评级,还有事件记录本身是完好的。请根据这些信息,还原旅行者记下的数字。 为了方便,我们认为事件之间的间隔足够长,以致在任意一次旅行中,所有城市的评级和信仰保持不变。

输入输出格式

输入格式:

 

输入的第一行包含整数N,Q依次表示城市数和事件数。

接下来N行,第i+l行两个整数Wi,Ci依次表示记录开始之前,城市i的评级和信仰。 接下来N-1行每行两个整数x,y表示一条双向道路。

接下来Q行,每行一个操作,格式如上所述。

 

输出格式:

 

对每个QS和QM事件,输出一行,表示旅行者记下的数字。

 

输入输出样例

输入样例#1: 
  1. 5 6
  2. 3 1
  3. 2 3
  4. 1 2
  5. 3 3
  6. 5 1
  7. 1 2
  8. 1 3
  9. 3 4
  10. 3 5
  11. QS 1 5
  12. CC 3 1
  13. QS 1 5
  14. CW 3 3
  15. QS 1 5
  16. QM 2 4
输出样例#1: 
  1. 8
  2. 9
  3. 11
    3

说明

N,Q < =10^5 , C < =10^5

数据保证对所有QS和QM事件,起点和终点城市的信仰相同;在任意时

刻,城市的评级总是不大于10^4的正整数,且宗教值不大于C。

思路

对于每个信仰都要开一个线段树,但如果是用常规的方法写线段树会MLE,所以需要用动态开点的方法来写线段树

  1. 1 #include<iostream>
  2. 2 #include<cstring>
  3. 3 #include<algorithm>
  4. 4 #include<cstdio>
  5. 5 #include<string>
  6. 6 #include<cmath>
  7. 7 #include<queue>
  8. 8 #include<vector>
  9. 9 #include<set>
  10. 10 #define maxn 100005
  11. 11 using namespace std;
  12. 12 struct sair{
  13. 13 int w,c;
  14. 14 }city[maxn];
  15. 15 struct Tree{
  16. 16 int l,r,sum,Max;
  17. 17 }tree[maxn*40];
  18. 18 int root[maxn];
  19. 19 vector<int>ve[maxn];
  20. 20 int dep[maxn],fa[maxn],siz[maxn],son[maxn],id[maxn],top[maxn];
  21. 21 int cnt,n;
  22. 22
  23. 23 void pushup(int rt){
  24. 24 tree[rt].sum=tree[tree[rt].l].sum+tree[tree[rt].r].sum;
  25. 25 tree[rt].Max=max(tree[tree[rt].l].Max,tree[tree[rt].r].Max);
  26. 26 }
  27. 27
  28. 28 void add(int cur,int l,int r,int p,int v){
  29. 29 if(l==r){
  30. 30 tree[cur].sum=v;
  31. 31 tree[cur].Max=v;
  32. 32 return;
  33. 33 }
  34. 34 int mid=(l+r)/2;
  35. 35 if(p<=mid){
  36. 36 if(!tree[cur].l){
  37. 37 tree[cur].l=++cnt;
  38. 38 }
  39. 39 add(tree[cur].l,l,mid,p,v);
  40. 40 }
  41. 41 else{
  42. 42 if(!tree[cur].r){
  43. 43 tree[cur].r=++cnt;
  44. 44 }
  45. 45 add(tree[cur].r,mid+1,r,p,v);
  46. 46 }
  47. 47 pushup(cur);
  48. 48 }
  49. 49
  50. 50 int querysum(int L,int R,int cur,int l,int r){
  51. 51 if(!cur) return 0;
  52. 52 if(L<=l&&R>=r){
  53. 53 return tree[cur].sum;
  54. 54 }
  55. 55 int mid=(l+r)/2;
  56. 56 int ans=0;
  57. 57 if(L<=mid) ans+=querysum(L,R,tree[cur].l,l,mid);
  58. 58 if(R>mid) ans+=querysum(L,R,tree[cur].r,mid+1,r);
  59. 59 return ans;
  60. 60 }
  61. 61
  62. 62 int querymax(int L,int R,int cur,int l,int r){
  63. 63 if(!cur) return 0;
  64. 64 if(L<=l&&R>=r){
  65. 65 return tree[cur].Max;
  66. 66 }
  67. 67 int mid=(l+r)/2;
  68. 68 int ans=0;
  69. 69 if(L<=mid) ans=max(ans,querymax(L,R,tree[cur].l,l,mid));
  70. 70 if(R>mid) ans=max(ans,querymax(L,R,tree[cur].r,mid+1,r));
  71. 71 return ans;
  72. 72 }
  73. 73
  74. 74 void dfs1(int now,int f,int deep){
  75. 75 dep[now]=deep;
  76. 76 siz[now]=1;
  77. 77 fa[now]=f;
  78. 78 int maxson=-1;
  79. 79 for(int i=0;i<ve[now].size();i++){
  80. 80 if(ve[now][i]==f) continue;
  81. 81 dfs1(ve[now][i],now,deep+1);
  82. 82 siz[now]+=siz[ve[now][i]];
  83. 83 if(siz[ve[now][i]]>maxson){
  84. 84 maxson=siz[ve[now][i]];
  85. 85 son[now]=ve[now][i];
  86. 86 }
  87. 87 }
  88. 88 }
  89. 89
  90. 90 void dfs2(int now,int topp){
  91. 91 id[now]=++cnt;
  92. 92 top[now]=topp;
  93. 93 if(!son[now]) return;
  94. 94 dfs2(son[now],topp);
  95. 95 for(int i=0;i<ve[now].size();i++){
  96. 96 if(ve[now][i]==son[now]||ve[now][i]==fa[now]) continue;
  97. 97 dfs2(ve[now][i],ve[now][i]);
  98. 98 }
  99. 99 }
  100. 100
  101. 101 int sumRange(int x,int y,int type){
  102. 102 int ans=0;
  103. 103 while(top[x]!=top[y]){
  104. 104 if(dep[top[x]]<dep[top[y]]) swap(x,y);
  105. 105 ans+=querysum(id[top[x]],id[x],type,1,n);
  106. 106 x=fa[top[x]];
  107. 107 }
  108. 108 if(dep[x]>dep[y]) swap(x,y);
  109. 109 ans+=querysum(id[x],id[y],type,1,n);
  110. 110 return ans;
  111. 111 }
  112. 112
  113. 113 int maxRange(int x,int y,int type){
  114. 114 int ans=0;
  115. 115 while(top[x]!=top[y]){
  116. 116 if(dep[top[x]]<dep[top[y]]) swap(x,y);
  117. 117 ans=max(ans,querymax(id[top[x]],id[x],type,1,n));
  118. 118 x=fa[top[x]];
  119. 119 }
  120. 120 if(dep[x]>dep[y]) swap(x,y);
  121. 121 ans=max(ans,querymax(id[x],id[y],type,1,n));
  122. 122 return ans;
  123. 123 }
  124. 124
  125. 125 int main(){
  126. 126
  127. 127 int q;
  128. 128 scanf("%d %d",&n,&q);
  129. 129 for(int i=1;i<=n;i++){
  130. 130 scanf("%d %d",&city[i].w,&city[i].c);
  131. 131 }
  132. 132 int x,y;
  133. 133 for(int i=1;i<n;i++){
  134. 134 scanf("%d %d",&x,&y);
  135. 135 ve[x].push_back(y);
  136. 136 ve[y].push_back(x);
  137. 137 }
  138. 138 cnt=0;
  139. 139 dfs1(1,0,1);
  140. 140 dfs2(1,1);
  141. 141 cnt=0;
  142. 142 for(int i=1;i<=n;i++){
  143. 143 if(!root[city[i].c]){
  144. 144 root[city[i].c]=++cnt;
  145. 145 }
  146. 146 add(root[city[i].c],1,n,id[i],city[i].w);
  147. 147 }
  148. 148 char pos[5];
  149. 149 for(int i=1;i<=q;i++){
  150. 150 scanf("%s %d %d",pos,&x,&y);
  151. 151 if(pos[1]=='S'){
  152. 152 printf("%d\n",sumRange(x,y,root[city[x].c]));
  153. 153 }
  154. 154 else if(pos[1]=='C'){
  155. 155 add(root[city[x].c],1,n,id[x],0);
  156. 156 city[x].c=y;
  157. 157 if(!root[city[x].c]){
  158. 158 root[city[x].c]=++cnt;
  159. 159 }
  160. 160 add(root[city[x].c],1,n,id[x],city[x].w);
  161. 161 }
  162. 162 else if(pos[1]=='W'){
  163. 163 city[x].w=y;
  164. 164 if(!root[city[x].c]){
  165. 165 root[city[x].c]=++cnt;
  166. 166 }
  167. 167 add(root[city[x].c],1,n,id[x],city[x].w);
  168. 168 }
  169. 169 else if(pos[1]=='M'){
  170. 170 printf("%d\n",maxRange(x,y,root[city[x].c]));
  171. 171 }
  172. 172 }
  173. 173 }
View Code

 

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号