hdu5967
Posted phile的空间
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu5967相关的知识,希望对你有一定的参考价值。
看到合肥赛区的题目都是泪啊,期末考完了来补几道
公正来说,这道题我考场确实写不出来,因为我的lct模板不够完美……
我在学习lct的时候不知道为什么代码里加边、删边都是用了一个makeroot的操作
这样我的lct就只能维护无根树而不能维护有根树
但事实上,lct是完全可以维护像这道题有向基环外向树一类有根树
那么怎么加边删边呢?
加边x和x的父亲y:只要先access(x) 再把x所属的Auxiliary Tree的Path parent更改y即可(即splay(x),fa[x]=y)
删除x和x的父亲y:先access(x),splay(x),这时断开Auxiliary Tree上根与左子树的连接即可
当然如果涉及到换根的操作,那还是要用makeroot的,这样lct就能维护有根树了
这道题,我们就是维护森林,成环的边不加(根如果有后继先不加),当遇到修改后继的时候再考虑根的后继是否可以加入,查询即找根是否有后继即可
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 int son[200010][2],a[200010],fa[200010]; 5 int n,m,pre; 6 bool rev[200010],can[200010]; 7 bool root(int x) 8 { 9 return (son[fa[x]][0]!=x&&son[fa 10 11 [x]][1]!=x); 12 } 13 14 void rot(int x,int w) 15 { 16 int y=fa[x]; 17 if (!root(y)) 18 { 19 if (son[fa[y]][0]==y) son[fa 20 21 [y]][0]=x; 22 else son[fa[y]][1]=x; 23 } 24 fa[x]=fa[y]; 25 son[y][w^1]=son[x][w]; 26 if (son[x][w]) fa[son[x][w]]=y; 27 son[x][w]=y; fa[y]=x; 28 } 29 30 void splay(int x) 31 { 32 while (!root(x)) 33 { 34 int y=fa[x]; 35 if (root(y)) 36 { 37 if (son[y][0]==x) rot(x,1); 38 39 else rot(x,0); 40 } 41 else { 42 if (son[fa[y]][0]==y) 43 { 44 if (son[y][0]==x) rot 45 46 (y,1); else rot(x,0); 47 rot(x,1); 48 } 49 else { 50 if (son[y][1]==x) rot 51 52 (y,0); else rot(x,1); 53 rot(x,0); 54 } 55 } 56 } 57 } 58 59 void access(int x) 60 { 61 int y=0; 62 while (x) 63 { 64 splay(x); 65 son[x][1]=y; 66 y=x; x=fa[x]; 67 } 68 } 69 70 int ask(int x) 71 { 72 access(x); 73 splay(x); 74 while (son[x][0]) x=son[x][0]; 75 return x; 76 } 77 78 void link(int x,int y) 79 { 80 access(x); 81 splay(x); 82 fa[x]=y; 83 } 84 85 void cut(int x) 86 { 87 access(x); 88 splay(x); 89 int y=son[x][0]; 90 if (!y) return; 91 fa[y]=son[x][0]=0; 92 } 93 94 void change(int x,int y) 95 { 96 if (y==a[x]) return; 97 int rt=ask(x); 98 if (can[x]) cut(x); 99 if (x!=rt&&a[rt]&&ask(a[rt])!=ask 100 101 (rt)) 102 { 103 link(rt,a[rt]); 104 can[rt]=1; 105 } 106 if (!y) can[x]=0; 107 else { 108 if (ask(x)!=ask(y)) 109 { 110 link(x,y); 111 can[x]=1; 112 } 113 else can[x]=0; 114 } 115 a[x]=y; 116 } 117 118 int main() 119 { 120 scanf("%d%d",&n,&m); 121 for (int i=1; i<=n; i++) 122 { 123 scanf("%d",&a[i]); 124 can[i]=0; 125 if (a[i]) 126 { 127 if (ask(a[i])!=ask(i)) 128 { 129 fa[i]=a[i]; 130 can[i]=1; 131 } 132 else can[i]=0; 133 } 134 } 135 int ch,x,y; 136 for (int i=1; i<=m; i++) 137 { 138 scanf("%d",&ch); 139 if (ch==1) 140 { 141 scanf("%d%d",&x,&y); 142 change(x,y); 143 } 144 else { 145 scanf("%d",&x); 146 y=ask(x); 147 printf("%d\\n",a[y]?-1:y); 148 } 149 } 150 }
以上是关于hdu5967的主要内容,如果未能解决你的问题,请参考以下文章
HDU4057 Rescue the Rabbit(AC自动机+状压DP)
HDU3247 Resource Archiver(AC自动机+BFS+DP)