比较有趣的综合树上问题,刷LCT题单时做的但是发现后面LCT只是起了辅助作用233

首先我们分析每一个操作,\(1\)的定义就让我们联想到了access,我们回忆一下LCT的性质:

LCT中每一个splay保存的都是原树上深度连续的一条链。

那么我们发现由于这里的染色是染上全新的一种颜色,所以每一次access后的每棵splay维护的都是同种颜色的点链,是同时符合性质和题目要求的

不过注意由于这里是染新的颜色,所以是可以用access的,如果是染成之前的某种颜色那么就不能这么做!

好了想完修改我们来考虑询问,首先看\(2\)操作,询问路径的颜色个数?

由于这是一棵有根树,结合前面的操作我们容易想到维护每个点到根节点的颜色个数记为\(col_i\)

容易发现这里的\(col\)具有可减性,那么维护路径颜色个数就可以用树上差分

具体的,路径\(x,y\)之间的颜色个数就是\(col_x+col_y-2\cdot col_{\operatorname{LCA}(x,y)}+1\)

这个和求树上两点间距离类似,不过就是\(\operatorname{LCA}\)的颜色会被减两次所以要加回去

然后就是\(3\)操作,我们发现当我们维护了\(col\)之后其实就是询问一个子树内最大的\(col\)

子树信息想到什么,DFS序啊!结合前面的access时进行的也是子树修改,我们容易想到维护区间修改区间查最大值线段树,这样结合access的期望\(\log\)复杂度是\(O(n\log^2n)\)的(复杂度分析类似于LCT上的平衡树操作)

那么就代码实现方面,DFS序都要写了,那么顺带写一下树剖吧,一般跳的比倍增快一些

然后就是码农时刻了,建议把代码分块一下要不然很容易调死不出

奉上近\(200\)行的CODE

  1. #include<cstdio>
  2. #include<cctype>
  3. #define RI register int
  4. #define CI const int&
  5. #define Tp template <typename T>
  6. using namespace std;
  7. const int N=100005;
  8. struct edge
  9. {
  10. int to,nxt;
  11. }e[N<<1]; int n,m,head[N],cnt,opt,x,y,fa,id[N],dep[N],dfn[N],size[N];
  12. class FileInputOutput
  13. {
  14. private:
  15. static const int S=1<<21;
  16. #define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,S,stdin),A==B)?EOF:*A++)
  17. #define pc(ch) (Ftop<S?Fout[Ftop++]=ch:(fwrite(Fout,1,S,stdout),Fout[(Ftop=0)++]=ch))
  18. char Fin[S],Fout[S],*A,*B; int pt[15],Ftop;
  19. public:
  20. Tp inline void read(T& x)
  21. {
  22. x=0; char ch; while (!isdigit(ch=tc()));
  23. while (x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));
  24. }
  25. Tp inline void write(T x)
  26. {
  27. if (!x) return (void)(pc('0'),pc('\n')); RI ptop=0;
  28. while (x) pt[++ptop]=x%10,x/=10; while (ptop) pc(pt[ptop--]+48); pc('\n');
  29. }
  30. inline void Fend(void)
  31. {
  32. fwrite(Fout,1,Ftop,stdout);
  33. }
  34. #undef tc
  35. #undef pc
  36. }F;
  37. class Segment_Tree
  38. {
  39. private:
  40. struct Segment
  41. {
  42. int mx,tag;
  43. }node[N<<2];
  44. #define M(x) node[x].mx
  45. #define T(x) node[x].tag
  46. inline int max(CI a,CI b)
  47. {
  48. return a>b?a:b;
  49. }
  50. inline void add(CI now,CI mv)
  51. {
  52. M(now)+=mv; T(now)+=mv;
  53. }
  54. inline void pushup(CI now)
  55. {
  56. M(now)=max(M(now<<1),M(now<<1|1));
  57. }
  58. inline void pushdown(CI now)
  59. {
  60. if (T(now)) add(now<<1,T(now)),add(now<<1|1,T(now)),T(now)=0;
  61. }
  62. public:
  63. #define TN CI now=1,CI l=1,CI r=n
  64. inline void build(TN)
  65. {
  66. if (l==r) return (void)(M(now)=dep[id[l]]); int mid=l+r>>1;
  67. build(now<<1,l,mid); build(now<<1|1,mid+1,r); pushup(now);
  68. }
  69. #define O beg,end
  70. inline void modify(CI beg,CI end,CI mv,TN)
  71. {
  72. if (beg<=l&&r<=end) return add(now,mv); int mid=l+r>>1; pushdown(now);
  73. if (beg<=mid) modify(O,mv,now<<1,l,mid); if (end>mid) modify(O,mv,now<<1|1,mid+1,r); pushup(now);
  74. }
  75. inline int query(CI beg,CI end,TN)
  76. {
  77. if (beg<=l&&r<=end) return M(now); int mid=l+r>>1,ret=0; pushdown(now);
  78. if (beg<=mid) ret=max(ret,query(O,now<<1,l,mid)); if (end>mid) ret=max(ret,query(O,now<<1|1,mid+1,r)); return ret;
  79. }
  80. #undef TN
  81. #undef O
  82. #undef M
  83. #undef T
  84. }T;
  85. class Link_Cut_Tree
  86. {
  87. private:
  88. struct splay
  89. {
  90. int ch[2],fa;
  91. }node[N];
  92. #define lc(x) node[x].ch[0]
  93. #define rc(x) node[x].ch[1]
  94. #define fa(x) node[x].fa
  95. inline void connect(CI x,CI y,CI d)
  96. {
  97. node[fa(x)=y].ch[d]=x;
  98. }
  99. inline int identify(CI now)
  100. {
  101. return rc(fa(now))==now;
  102. }
  103. inline bool isroot(CI now)
  104. {
  105. return lc(fa(now))!=now&&rc(fa(now))!=now;
  106. }
  107. inline void rotate(CI now)
  108. {
  109. int x=fa(now),y=fa(x),d=identify(now); if (!isroot(x)) node[y].ch[identify(x)]=now;
  110. fa(now)=y; connect(node[now].ch[d^1],x,d); connect(x,now,d^1);
  111. }
  112. inline void splay(int now)
  113. {
  114. for (int t;!isroot(now);rotate(now))
  115. t=fa(now),!isroot(t)&&(rotate(identify(now)!=identify(t)?now:t),0);
  116. }
  117. inline int findroot(int now)
  118. {
  119. while (lc(now)) now=lc(now); return now;
  120. }
  121. public:
  122. inline void link(CI x,CI y)
  123. {
  124. fa(x)=y;
  125. }
  126. inline void access(int x)
  127. {
  128. for (int y=0,t;x;x=fa(y=x))
  129. {
  130. splay(x); if (rc(x)) t=findroot(rc(x)),T.modify(dfn[t],dfn[t]+size[t]-1,1);
  131. if (rc(x)=y) t=findroot(rc(x)),T.modify(dfn[t],dfn[t]+size[t]-1,-1);
  132. }
  133. }
  134. #undef lc
  135. #undef rc
  136. #undef fa
  137. }LCT;
  138. class Light_Heavy_Division
  139. {
  140. private:
  141. int idx,top[N],father[N],son[N];
  142. inline void swap(int& x,int& y)
  143. {
  144. int t=x; x=y; y=t;
  145. }
  146. public:
  147. #define to e[i].to
  148. inline void DFS1(CI now,CI fa)
  149. {
  150. size[now]=1; dep[now]=dep[fa]+1; father[now]=fa;
  151. for (RI i=head[now];i;i=e[i].nxt) if (to!=fa)
  152. {
  153. DFS1(to,now); size[now]+=size[to]; LCT.link(to,now);
  154. if (size[to]>size[son[now]]) son[now]=to;
  155. }
  156. }
  157. inline void DFS2(CI now,CI tf)
  158. {
  159. id[dfn[now]=++idx]=now; top[now]=tf;
  160. if (son[now]) DFS2(son[now],tf);
  161. for (RI i=head[now];i;i=e[i].nxt)
  162. if (to!=father[now]&&to!=son[now]) DFS2(to,to);
  163. }
  164. inline int get_LCA(int x,int y)
  165. {
  166. while (top[x]!=top[y])
  167. {
  168. if (dep[top[x]]<dep[top[y]]) swap(x,y);
  169. x=father[top[x]];
  170. }
  171. return dep[x]<dep[y]?x:y;
  172. }
  173. #undef to
  174. }L;
  175. inline void add(CI x,CI y)
  176. {
  177. e[++cnt]=(edge){y,head[x]}; head[x]=cnt;
  178. }
  179. int main()
  180. {
  181. //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
  182. RI i; for (F.read(n),F.read(m),i=1;i<n;++i) F.read(x),F.read(y),add(x,y),add(y,x);
  183. for (L.DFS1(1,0),L.DFS2(1,1),T.build(),i=1;i<=m;++i)
  184. {
  185. F.read(opt); F.read(x); switch (opt)
  186. {
  187. case 1:
  188. LCT.access(x); break;
  189. case 2:
  190. F.read(y); fa=L.get_LCA(x,y);
  191. F.write(T.query(dfn[x],dfn[x])+T.query(dfn[y],dfn[y])-
  192. (T.query(dfn[fa],dfn[fa])<<1)+1); break;
  193. case 3:
  194. F.write(T.query(dfn[x],dfn[x]+size[x]-1)); break;
  195. }
  196. }
  197. return F.Fend(),0;
  198. }

Luogu P3703 [SDOI2017]树点涂色的更多相关文章

  1. P3703 [SDOI2017]树点涂色

    P3703 [SDOI2017]树点涂色 链接 分析: 首先对于询问,感觉是线段树维护dfs序,每个点记录到根的颜色个数.第二问差分,第三问区间取max. 那么考虑修改,每次将一个点的颜色变成和父节点 ...

  2. P3703 [SDOI2017]树点涂色 LCT维护颜色+线段树维护dfs序+倍增LCA

    \(\color{#0066ff}{ 题目描述 }\) Bob有一棵\(n\)个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同. 定义一条路径的权值是:这条路径上的点 ...

  3. 洛谷P3703 [SDOI2017]树点涂色(LCT,dfn序,线段树,倍增LCA)

    洛谷题目传送门 闲话 这是所有LCT题目中的一个异类. 之所以认为是LCT题目,是因为本题思路的瓶颈就在于如何去维护同颜色的点的集合. 只不过做着做着,感觉后来的思路(dfn序,线段树,LCA)似乎要 ...

  4. 并不对劲的bzoj4817:loj2001:p3703:[SDOI2017]树点涂色

    题目大意 有一棵\(n\)(\(n\leq10^5\))个节点的树,每个点有颜色\(c\),一开始所有颜色互不相同 要进行\(m\)(\(m\leq10^5\))次操作,每次操作是以下三种中的一种: ...

  5. [Sdoi2017]树点涂色 [lct 线段树]

    [Sdoi2017]树点涂色 题意:一棵有根树,支持x到根染成新颜色,求x到y颜色数,求x子树里点到根颜色数最大值 考场发现这个信息是可减的,但是没想到lct 特意设计成lct的形式! 如何求颜色数? ...

  6. 【LG3703】[SDOI2017]树点涂色

    [LG3703][SDOI2017]树点涂色 题面 洛谷 题解 更博辣,更博辣!!! 猪年的第一篇博客 一次只能染根到\(x\),且染的颜色未出现过 这句话是我们解题的关键. 设\(x\)到根的颜色数 ...

  7. [BZOJ4817][SDOI2017]树点涂色(LCT+DFS序线段树)

    4817: [Sdoi2017]树点涂色 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 692  Solved: 408[Submit][Status ...

  8. 【BZOJ4817】[Sdoi2017]树点涂色 LCT+线段树

    [BZOJ4817][Sdoi2017]树点涂色 Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路径的权值是:这条路 ...

  9. [Bzoj4817] [Sdoi2017]树点涂色 (LCT神题)

    4817: [Sdoi2017]树点涂色 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 629  Solved: 371[Submit][Status ...

随机推荐

  1. 函数纹理(国际象棋棋盘纹理&粗布纹理)MFC

    函数纹理(国际象棋棋盘纹理&粗布纹理)MFC实现  源码百度云下载 国际象棋棋盘纹理(效果图见最后) //国际象棋纹理函数 //g(u, v) = a , 向下取整(8u)+向下取整(8v) ...

  2. 随笔:Oracle实验课(软件系统开发综合实践)B/S结构;java——图书管理系统

    以上是我需要注意的要求 -------------------------------此处为放假分割线-1-20----------------------------------- 初步完成了整个程 ...

  3. (python)数据结构---字符串

    一.概述 由一个个字符组成的有序序列. 使用单引号.双引号.三引号引住的字符序列. 不可变.线性的数据结构. 二.字符串的相关操作 1.元素访问----下标 字符串是线性的数据结构,可以使用索引去访问 ...

  4. MapReduce ----数据去重

    三个文件 2017-03-10 a2017-03-11 b2017-03-12 d2017-03-13 d2017-03-142017-03-15 a 2017-03-10 e2017-03-11 b ...

  5. Java读取.properties配置文件

    一.介绍 Properties文件在Java中主要为配置文件,文件类型为:.properties,格式为文本文件,内容格式为"键=值" 二.读取 这里我采用的是getResourc ...

  6. PostgreSQL 多级分区

    CREATE TABLE range_list (a int,b timestamp) PARTITION BY RANGE (b); CREATE TABLE range_pa1 PARTITION ...

  7. CENTOS7错误:Cannot find a valid baseurl for repo: base/7/x86_6

    CENTOS7错误:Cannot find a valid baseurl for repo: base/7/x86_6 解决办法: 1.进入/etc/sysconfig/network-script ...

  8. php获取ip地址所在的地理位置的实现

    1,通过腾讯或者新浪提供的接口来获取(新浪和腾讯类似) <?php     function getIPLocation($queryIP){      $url = 'http://ip.qq ...

  9. 好系统重装助手教你如何让win10系统快速开机

    电脑开机的时候,有一些自动开启的软件或工具会占用一定的开机时间,把它们禁止开机启动项就会提高电脑开机速度.很多人会借助360或者电脑管家等软件来设置,下面小编就来教大家一招不借助第三方工具来禁止win ...

  10. Linux系统挂载Windows的共享文件夹

    解决方案 在window上文件设置共享权限 在Linux上在 使用mount 命令挂载 Windows 共享文件夹 实验环境 redhat linux 7操作系统 服务器IP 192.168.100. ...