带 加点 删边的块状树。

加点在 bzoj3720 说过。

删边其实就是块顶打标记,记录其属于哪棵树,防止在dfs搜集答案时跑到别的树上。

然后暴力把所在块拆开。

好像用邻接表存图,直接在vector里删边也行?

  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<cmath>
  4. #include<vector>
  5. using namespace std;
  6. #define maxn 200001
  7. int Res,Num;char C,CH[];
  8. inline int Ge()
  9. {
  10. Res=;C='*';
  11. while(C<''||C>'')C=getchar();
  12. while(C>=''&&C<=''){Res=Res*+(C-'');C=getchar();}
  13. return Res;
  14. }
  15. inline void P(int x)
  16. {
  17. Num=;if(!x){putchar('');puts("");return;}
  18. while(x>)CH[++Num]=x%,x/=;
  19. while(Num)putchar(CH[Num--]+);
  20. putchar('\n');
  21. }
  22. typedef vector<int>::iterator ITER;
  23. vector<int>List[maxn],Goto[maxn];
  24. struct Graph
  25. {
  26. int v[maxn<<],first[maxn<<],next[maxn<<],en;
  27. void AddEdge(const int &a,const int &b)
  28. {v[++en]=b;next[en]=first[a];first[a]=en;}
  29. };
  30. Graph G,son;
  31. int top[maxn],siz[maxn],sz,w[maxn],belong_tree[maxn];
  32. bool vis[maxn],root[maxn];
  33. int n,x,y,m,op,tree_num;
  34. int ans,val,U;
  35. void makeblock(int cur)
  36. {
  37. vis[cur]=true;
  38. for(int i=G.first[cur];i;i=G.next[i])
  39. if(!vis[G.v[i]])
  40. {
  41. son.AddEdge(cur,G.v[i]);
  42. if(siz[top[cur]]<sz)
  43. {
  44. List[top[cur]].push_back(w[G.v[i]]);
  45. siz[top[cur]]++;
  46. top[G.v[i]]=top[cur];
  47. }
  48. makeblock(G.v[i]);
  49. }
  50. }
  51. void makeGoto(int cur)
  52. {
  53. for(int i=son.first[cur];i;i=son.next[i])
  54. {
  55. if(top[son.v[i]]!=top[cur])
  56. Goto[top[cur]].push_back(son.v[i]);
  57. makeGoto(son.v[i]);
  58. }
  59. }
  60. void dfs(int cur)//在Goto树上询问
  61. {
  62. ans+=( List[cur].end() - upper_bound( List[cur].begin() , List[cur].end() , val ) );
  63. for(ITER it=Goto[cur].begin();it!=Goto[cur].end();it++)
  64. if(belong_tree[*it]==belong_tree[cur])//通过标记控制在一棵树内
  65. dfs(*it);
  66. }
  67. void dfs_block(int cur)//在块内询问
  68. {
  69. if(w[cur]>val) ans++;
  70. for(int i=son.first[cur];i;i=son.next[i])
  71. if(top[son.v[i]]==top[cur]) dfs_block(son.v[i]);
  72. else if(belong_tree[son.v[i]]==belong_tree[top[cur]]) dfs(son.v[i]);
  73. }
  74. void query()
  75. {
  76. ans=;
  77. if(U==top[U]) dfs(U);
  78. else dfs_block(U);
  79. P(ans);
  80. }
  81. void update()
  82. {
  83. List[top[U]].erase( lower_bound(List[top[U]].begin(),List[top[U]].end(),w[U]) );
  84. w[U]=val;
  85. List[top[U]].insert( lower_bound(List[top[U]].begin(),List[top[U]].end(),val+) , val );
  86. }
  87. void AddPoint()
  88. {
  89. n++;
  90. if(siz[top[U]]<sz)
  91. {
  92. top[n]=top[U];
  93. siz[top[n]]++;
  94. }
  95. else
  96. {
  97. top[n]=n;
  98. siz[n]++;
  99. Goto[top[U]].push_back(n);
  100. belong_tree[n]=belong_tree[top[U]];
  101. }
  102. son.AddEdge(U,n);
  103. w[n]=val;
  104. List[top[n]].insert( lower_bound(List[top[n]].begin(),List[top[n]].end(),val+) , val );
  105. }
  106. void dfs_split(int cur)//设置每个块顶属于哪个树的标记
  107. {
  108. for(ITER it=Goto[cur].begin();it!=Goto[cur].end();it++)
  109. if(belong_tree[cur]==belong_tree[*it])
  110. dfs_split(*it);
  111. belong_tree[cur]=tree_num;
  112. }
  113. void dfs_split_block(int cur)//把分裂的块的下半部分重构块
  114. {
  115. List[U].push_back(w[cur]);
  116. for(int i=son.first[cur];i;i=son.next[i])
  117. {
  118. if(top[son.v[i]]==top[cur])
  119. dfs_split_block(son.v[i]);
  120. else if(belong_tree[son.v[i]]==belong_tree[top[U]])//顺手设置它下面的块的标记
  121. {
  122. Goto[U].push_back(son.v[i]);
  123. dfs_split(son.v[i]);
  124. }
  125. siz[U]++;
  126. }
  127. top[cur]=U;
  128. }
  129. void dfs_remain_block(int cur)//把分裂的块的上半部分重构块
  130. {
  131. List[top[U]].push_back(w[cur]); siz[top[U]]++;
  132. for(int i=son.first[cur];i;i=son.next[i])
  133. if( (!root[son.v[i]]) && (top[son.v[i]]==top[cur]) )
  134. dfs_remain_block(son.v[i]);
  135. }
  136. void Delete_Edge()
  137. {
  138. root[U]=true;
  139. tree_num++;
  140. if(U!=top[U])
  141. {
  142. List[top[U]].clear();siz[top[U]]=;
  143. dfs_remain_block(top[U]);
  144. sort(List[top[U]].begin(),List[top[U]].end());//重构分裂的块的上半部分
  145. dfs_split_block(U);
  146. belong_tree[U]=tree_num;
  147. sort(List[U].begin(),List[U].end());//重构分裂的块的下半部分
  148. }
  149. else
  150. dfs_split(U);
  151. }
  152. int main()
  153. {
  154. n=Ge();
  155. for(int i=;i<n;i++)
  156. {
  157. x=Ge();y=Ge();
  158. G.AddEdge(x,y);
  159. G.AddEdge(y,x);
  160. }
  161. sz=sqrt((double)n*log2(n));
  162. for(int i=;i<=n;i++)
  163. {
  164. w[i]=Ge();
  165. top[i]=i;
  166. siz[i]=;
  167. }
  168. makeblock();
  169. for(int i=;i<=n;i++)
  170. if(top[i]==i)
  171. {
  172. List[i].push_back(w[i]);
  173. sort(List[i].begin(),List[i].end());
  174. }
  175. makeGoto();
  176. root[]=true;
  177. m=Ge();
  178. for(int i=;i<=m;i++)
  179. {
  180. op=Ge();U=Ge();U^=ans;
  181. if(!op){val=Ge();val^=ans;query();}
  182. else if(op==){val=Ge();val^=ans;update();}
  183. else if(op==){val=Ge();val^=ans;AddPoint();}
  184. else Delete_Edge();
  185. }
  186. return ;
  187. }

【块状树】bzoj3731 Gty的超级妹子树的更多相关文章

  1. bzoj3731: Gty的超级妹子树

    一代神题啊orz(至少是以前年代的神题吧) 块状树 复杂度nsqrtnlogn 真是exciting 还没有卡时限 话不多说直接上代码 (最近解锁了记事本写代码的技能...感觉越来越依赖OJ调试了.. ...

  2. BZOJ 3731: Gty的超级妹子树

    3731: Gty的超级妹子树 Time Limit: 7 Sec  Memory Limit: 32 MBSubmit: 346  Solved: 96[Submit][Status][Discus ...

  3. bzoj3731: Gty的超级妹子树(树分块)

    传送门 分块树,代码参考了Manchery的 具体细节还是看代码好了 这题卡常……注意常数写好点…… //minamoto #include<iostream> #include<c ...

  4. bzoj Gty的超级妹子树 块状树

    Gty的超级妹子树 Time Limit: 7 Sec  Memory Limit: 32 MBSubmit: 500  Solved: 122[Submit][Status][Discuss] De ...

  5. 【块状树】bzoj3720 Gty的妹子树

    块状树.教程见:http://z55250825.blog.163.com/blog/static/1502308092014163413858/将树按一定大小分块,分成许多子树,在每个子树的根节点记 ...

  6. BZOJ3720 Gty的妹子树

    Description 我曾在弦歌之中听过你, 檀板声碎,半出折子戏. 舞榭歌台被风吹去, 岁月深处尚有余音一缕…… Gty神(xian)犇(chong)从来不缺妹子…… 他来到了一棵妹子树下,发现每 ...

  7. BZOJ 3720 gty的妹子树

    块状树裸题 块状树: 首先对树进行分块,分出的每一块都是一个连通块 通常的分块的方式如下: 1.父亲所在块不满,分到父亲所在块中 2.父亲所在块满,自己单独开一个块 (貌似有更为优越的分块方式? 注意 ...

  8. bzoj 3720: Gty的妹子树 块状树

    3720: Gty的妹子树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 412  Solved: 153[Submit][Status] Descr ...

  9. 【BZOJ3720】Gty的妹子树 块状树

    [BZOJ3720]Gty的妹子树 我曾在弦歌之中听过你,檀板声碎,半出折子戏.舞榭歌台被风吹去,岁月深处尚有余音一缕……Gty神(xian)犇(chong)从来不缺妹子……他来到了一棵妹子树下,发现 ...

随机推荐

  1. [05]Git查看、删除、重命名远程分支和tag

    Git查看.删除.重命名远程分支和tag 2015-06-15:加入姊妹篇: 2013-11-06:加入重命名远程分支的内容: 2013-01-09:加入删除远程tag的内容. 姊妹篇:使用Git.G ...

  2. Spring 学习笔记(一)

    一.Spring 是什么? •Spring 是一个开源框架. •Spring 为简化企业级应用开发而生. 使用 Spring 可以使简单的 JavaBean 实现以前只有 EJB 才能实现的功能. • ...

  3. POJ 2456 Aggressive cows---二分搜索法

    ///3.最大化最小值 /** POJ 2456 Aggressive cows Q:一排牛舍有N (2 <= N <= 100,000) 个,位置为x1,...,xN (0 <= ...

  4. 【洛谷 P4168】[Violet]蒲公英(分块)

    题目链接 题目大意:给定\(n\)个数和\(m\)个求区间众数的询问,强制在线 这题我\(debug\)了整整一个下午啊..-_- 从14:30~16:45终于\(debug\)出来了,\(debug ...

  5. 单源最短路模板_SPFA_Dijkstra(堆优化)_C++

    随手一打就是标准的SPFA,默认1号节点为出发点,当然不用 f 判断是否在队里也可以,只是这样更优化一点 void spfa() { int i,x,k; ;i<=n;i++) { d[i]=o ...

  6. bzoj 1942 斜率优化DP

    首先我们贪心的考虑,对于某一天来说,我们只有3中策略,第一种为不做任何行动,这时的答案与前一天相同,第二种为将自己的钱全部换成a,b货币,因为如果换a,b货币,代表在之后的某一天卖出去后会赚钱,那么当 ...

  7. bzoj 2245 费用流

    比较裸 源点连人,每个人连自己的工作,工作连汇,然后因为人的费用是 分度的,且是随工作数非降的,所以我们拆边,源点连到每个人s+1条边 容量是每段的件数,费用是愤怒 /**************** ...

  8. 常见的makefile写法【转】

    转自:http://blog.csdn.net/ghostyu/article/details/7755177 版权声明:本文为博主原创文章,未经博主允许不得转载. .目标名称,摆脱手动设置目标名称 ...

  9. Python selenium.webdriver.chrome.options.Options() Examples

    The following are 27 code examples for showing how to use selenium.webdriver.chrome.options.Options( ...

  10. json相关注解和序列化与反序列化

    使用jackson进行序列化时,往往会遇到后台某个实体对象的属性为null,当序列化成json时对应的属性也为null,可以用以下的注解方式完成当属性为null时不参与序列化: @JsonSerial ...