[关闭]
@11101001 2018-03-24T21:32:57.000000Z 字数 3212 阅读 762

bzoj4817: [Sdoi2017]树点涂色


题目链接

bzoj4817: [Sdoi2017]树点涂色

题解

数据结构.....大概很容易看出是道lct 然后弃疗
操作1很想lct里面的access操作
那么对于操作2
设F[i]=i点到lct根路径上的splay数(也就是虚边数)+1
那么对于操作2的(x,y)
ans(x,y)=F[x]+F[y]-(F(lca(x,y)))+1;
对于操作3的(x),就是在x的子树中取max,我们可以用dfs序+线段树维护
考虑操作1对操作3的影响
在access的时候,当一个边由虚变实,此时该边所连的深度大的点的颜色种类-1
反之当一边由实变虚,此时该边所连的深度大的点的颜色种类+1
trick:保存当前节点在树中最左儿子的编号用以修改区间(即left[])
ps:中途电脑爆炸,然后重码QAQ,心态爆炸

代码

  1. /*
  2. *
  3. * 数据结构+LCT+SEG_TREE
  4. *
  5. */
  6. #include<cstdio>
  7. #include<algorithm>
  8. const int maxn = 100007;
  9. int n,m;
  10. struct node{
  11. int v,next;
  12. }edge[maxn<<1];
  13. int head[maxn],num;
  14. void Add_Edge(int u,int v) {
  15. edge[++num].v=v;edge[num].next=head[u];head[u]=num;
  16. }
  17. int idfn[maxn],ldfn[maxn],rdfn[maxn],f[maxn][20],dep[maxn];
  18. int cnt=0,fa[maxn];
  19. void dfs(int u,int F) {
  20. idfn[ldfn[u]=++cnt]=u,f[u][0]=fa[u]=F;
  21. for(int i=head[u];i;i=edge[i].next) {
  22. int v=edge[i].v;
  23. if(v!=F) dep[v]=dep[u]+1,dfs(v,u);
  24. }
  25. rdfn[u]=cnt;
  26. return ;
  27. }
  28. int LCA(int x,int y) {
  29. if(dep[x]<dep[y]) std::swap(x,y);
  30. for(int i=dep[x]-dep[y],j=0;i;i>>=1,++j)
  31. if(i&1)x=f[x][j];
  32. if(x==y) return x;
  33. for(int i=19;~i;--i)
  34. if(f[x][i]!=f[y][i])
  35. x=f[x][i],y=f[y][i];
  36. return f[x][0];
  37. }
  38. class Segment_Tree {
  39. #define lc x<<1
  40. #define rc x<<1|1
  41. private :
  42. struct Node {
  43. int max,tag;
  44. Node () : tag(0){}
  45. };
  46. Node t[maxn<<2];
  47. void update(int x) {
  48. t[x].max=std::max(t[lc].max,t[rc].max);
  49. }
  50. void push_down(int x) {
  51. if(!t[x].tag)return;
  52. int k=t[x].tag;
  53. t[lc].max+=k;
  54. t[lc].tag+=k;
  55. t[rc].max+=k;
  56. t[rc].tag+=k;
  57. t[x].tag=0;
  58. return ;
  59. }
  60. public :
  61. void build (int x,int l,int r) {
  62. if(l==r) {
  63. t[x].max=dep[idfn[l]]+1;return;
  64. }
  65. int mid=l+r>>1;
  66. build(lc,l,mid);
  67. build(rc,mid+1,r);
  68. return update(x);
  69. }
  70. void modify(int x,int l,int r,int L,int R,int w) {
  71. if(L<=l&&R>=r) {
  72. t[x].tag+=w;t[x].max+=w;
  73. return ;
  74. }
  75. push_down(x);
  76. int mid=l+r>>1;
  77. if(mid>=L) modify(lc,l,mid,L,R,w);
  78. if(mid<R) modify(rc,mid+1,r,L,R,w);
  79. return update(x);
  80. }
  81. int query(int x,int l,int r,int L,int R) {
  82. if(L<=l&&R>=r)
  83. return t[x].max;
  84. push_down(x);
  85. int mid=l+r>>1,ans=0;
  86. if(mid>=L) ans=std::max(ans,query(lc,l,mid,L,R));
  87. if(mid<R) ans=std::max(ans,query(rc,mid+1,r,L,R));
  88. return ans;
  89. }
  90. #undef lc
  91. #undef rc
  92. }SEG_T;
  93. class Link_Cut_tree {
  94. #define lc ch[x][0]
  95. #define rc ch[x][1]
  96. private :
  97. int ch[maxn][2],left[maxn];
  98. void update(int x) {
  99. left[x]=lc ? left[lc]:x;
  100. }
  101. bool isroot(int x) {
  102. return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;
  103. }
  104. void rotate(int x) {
  105. int y=fa[x],z=fa[y],d=(ch[y][1]==x)^1;
  106. if(!isroot(y)) ch[z][ch[z][1]==y]=x;fa[x]=z;
  107. ch[y][d^1]=ch[x][d],fa[ch[x][d]]=y;
  108. ch[x][d]=y;fa[y]=x;
  109. update(y),update(x);
  110. }
  111. void splay(int x) {
  112. while(!isroot(x)) {
  113. int y=fa[x],z=fa[y];
  114. if(!isroot(y)) {
  115. if(ch[y][1]==x^ch[z][1]==y) rotate(x);
  116. else rotate(y);
  117. }
  118. rotate(x);
  119. }
  120. }
  121. public:
  122. void init() {
  123. dfs(1,0),SEG_T.build(1,1,n);
  124. for(int i=1;i<=n;++i) left[i]=i;
  125. for(int j=1;j<20;j++)
  126. for(int i=1;i<=n;i++)
  127. f[i][j]=f[f[i][j-1]][j-1];
  128. }
  129. void access(int x) {
  130. for(int t=0;x;x=fa[t=x]) {
  131. splay(x);
  132. if(rc) SEG_T.modify(1,1,n,ldfn[left[rc]],rdfn[left[rc]],1);
  133. rc=t;
  134. if(rc) SEG_T.modify(1,1,n,ldfn[left[rc]],rdfn[left[rc]],-1);
  135. }
  136. return ;
  137. }
  138. int query(int x) {
  139. int ans=0;
  140. for(;x;x=fa[x],ans++)splay(x);
  141. return ans;
  142. }
  143. int query(int u,int v) {
  144. return query(u)+query(v)-2*query(LCA(u,v))+1;
  145. }
  146. #undef lc
  147. #undef rc
  148. }LCT;
  149. int main() {
  150. // freopen("001.out","w",stdout);
  151. scanf("%d%d",&n,&m) ;
  152. for(int a,b,i=1;i<n;++i) {
  153. scanf("%d%d",&a,&b);
  154. Add_Edge(a,b);
  155. Add_Edge(b,a);
  156. }
  157. LCT.init();
  158. for(int opt,x,y,i=1;i<=m;++i) {
  159. scanf("%d",&opt);
  160. if(opt==1) scanf("%d",&x),LCT.access(x);
  161. if(opt==2) scanf("%d%d",&x,&y),printf("%d\n",LCT.query(x,y));
  162. else if(opt==3) scanf("%d",&x),printf("%d\n",SEG_T.query(1,1,n,ldfn[x],rdfn[x]));
  163. }
  164. return 0;
  165. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注