Codeforces Round #563 (Div. 2) F. Ehab and the Big Finale
后续:
点分治标程
使用father数组
比使用vis数组优秀(不需要对vis初始化)
https://codeforces.com/problemset/problem/1174/F
https://codeforces.com/blog/entry/67388
有助于理解树链剖分 和 点分治
题解写得挺好
重链
重链中的点的子树的大小是最大的
重链外的点作为根节点的 子树 大小 < 1/2总的点数目
每次处理后到达重链外的点(若是重链内的点,判断结束)
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <iostream> 8 using namespace std; 9 #define ll long long 10 11 12 const double eps=1e-8; 13 const ll inf=1e9; 14 const ll mod=1e9+7; 15 const int maxn=2e5+10; 16 17 struct node 18 { 19 int d; 20 node *to; 21 }*e[maxn]; 22 23 char str[20]; 24 int siz[maxn],fa[maxn],link[maxn],cnt_link; 25 26 void dfs(int d) 27 { 28 node *p=e[d]; 29 siz[d]=1; 30 while (p) 31 { 32 if (fa[d]!=p->d) 33 { 34 fa[p->d]=d; 35 dfs(p->d); 36 siz[d]+=siz[p->d]; 37 } 38 p=p->to; 39 } 40 } 41 42 void findleaf(int d) 43 { 44 node *p; 45 int num; 46 cnt_link=0; 47 link[0]=d; 48 while (1) 49 { 50 p=e[d]; 51 num=0; 52 while (p) 53 { 54 if (fa[d]!=p->d) 55 { 56 if (siz[p->d]>siz[num]) 57 num=p->d; 58 } 59 p=p->to; 60 } 61 if (!num) 62 break; 63 link[++cnt_link]=num; 64 d=num; 65 } 66 } 67 68 int main() 69 { 70 node *p; 71 int n,x,y,i,root,dist,r,pos; 72 scanf("%d",&n); 73 for (i=1;i<n;i++) 74 { 75 scanf("%d%d",&x,&y); 76 p=new node(); 77 p->d=y; 78 p->to=e[x]; 79 e[x]=p; 80 81 p=new node(); 82 p->d=x; 83 p->to=e[y]; 84 e[y]=p; 85 } 86 gets(str); 87 88 printf("d %d\n",1); 89 fflush(stdout); 90 scanf("%d",&dist); 91 if (dist==0) 92 { 93 printf("! %d\n",1); 94 fflush(stdout); 95 return 0; 96 } 97 98 root=1; 99 while (1) 100 { 101 dfs(root); 102 findleaf(root); 103 104 printf("d %d\n",link[cnt_link]); 105 fflush(stdout); 106 scanf("%d",&r); 107 108 pos=(dist+cnt_link-r)/2; 109 root=link[pos]; 110 dist=dist-pos; 111 if (dist==0) 112 { 113 printf("! %d\n",root); 114 fflush(stdout); 115 return 0; 116 } 117 118 printf("s %d\n",root); 119 fflush(stdout); 120 scanf("%d",&root); 121 dist--; 122 if (dist==0) 123 { 124 printf("! %d\n",root); 125 fflush(stdout); 126 return 0; 127 } 128 } 129 return 0; 130 } 131 /* 132 6 133 1 2 134 2 3 135 3 4 136 4 5 137 5 6 138 139 7 140 1 2 141 1 3 142 2 4 143 2 5 144 3 6 145 3 7 146 147 148 149 7 150 1 2 151 1 3 152 2 4 153 2 5 154 3 6 155 3 7 156 d 1 157 2 158 d 7 159 4 160 s 1 161 2 162 d 7 163 */
树重心(点分治)
作为树重心的点,若干个子树
max(size of subtree) 最小
子树的大小均小于 < 1/2总的点数目
每次处理后到达新当前树重心的子树(若是树重心,判断结束)
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <iostream> 8 using namespace std; 9 #define ll long long 10 11 const double eps=1e-8; 12 const ll inf=1e9; 13 const ll mod=1e9+7; 14 const int maxn=2e5+10; 15 16 /* 17 fa 18 用于cdq分治比较好 19 */ 20 21 struct node 22 { 23 int d; 24 node *to; 25 }*e[maxn]; 26 27 char str[20]; 28 int siz[maxn],fa[maxn],dep[maxn],minsiz,root,pre_root,nn; 29 bool hav[maxn]; 30 31 void dfs(int d) 32 { 33 int maxs=0; 34 node *p=e[d]; 35 siz[d]=1; 36 while (p) 37 { 38 if (fa[d]!=p->d && !hav[p->d]) 39 { 40 fa[p->d]=d; 41 dep[p->d]=dep[d]+1; 42 dfs(p->d); 43 siz[d]+=siz[p->d]; 44 maxs=max(maxs,siz[p->d]); 45 } 46 p=p->to; 47 } 48 maxs=max(maxs,nn-siz[d]); 49 if (maxs<minsiz) 50 minsiz=maxs,root=d; 51 } 52 53 int main() 54 { 55 node *p; 56 int n,x,y,i,r,dist; 57 scanf("%d",&n); 58 for (i=1;i<n;i++) 59 { 60 scanf("%d%d",&x,&y); 61 p=new node(); 62 p->d=y; 63 p->to=e[x]; 64 e[x]=p; 65 66 p=new node(); 67 p->d=x; 68 p->to=e[y]; 69 e[y]=p; 70 } 71 gets(str); 72 73 printf("d %d\n",1); 74 fflush(stdout); 75 scanf("%d",&dist); 76 if (dist==0) 77 { 78 printf("! %d\n",1); 79 fflush(stdout); 80 return 0; 81 } 82 83 nn=n; 84 root=1; 85 while (1) 86 { 87 pre_root=root; 88 dep[pre_root]=0; 89 minsiz=inf; 90 dfs(root); 91 92 if (root==pre_root) 93 { 94 printf("s %d\n",root); 95 fflush(stdout); 96 hav[root]=1; 97 scanf("%d",&root); 98 dist--; 99 if (dist==0) 100 { 101 printf("! %d\n",root); 102 fflush(stdout); 103 return 0; 104 } 105 nn=siz[root]; 106 } 107 else 108 { 109 printf("d %d\n",root); 110 fflush(stdout); 111 scanf("%d",&r); 112 113 if (r==0) 114 { 115 printf("! %d\n",root); 116 fflush(stdout); 117 return 0; 118 } 119 120 hav[root]=1; 121 if (r+dep[root]==dist) 122 { 123 printf("s %d\n",root); 124 fflush(stdout); 125 dist-=dep[root]+1; 126 scanf("%d",&root); 127 128 if (dist==0) 129 { 130 printf("! %d\n",root); 131 fflush(stdout); 132 return 0; 133 } 134 nn=siz[root]; 135 } 136 else 137 { 138 nn=siz[pre_root]-siz[root]; 139 root=pre_root;///so that no need to initialize array fa 140 ///dist not change 141 } 142 } 143 } 144 return 0; 145 } 146 /* 147 6 148 1 2 149 2 3 150 3 4 151 4 5 152 5 6 153 154 7 155 1 2 156 1 3 157 2 4 158 2 5 159 3 6 160 3 7 161 162 15 163 1 2 164 1 3 165 2 4 166 2 5 167 3 6 168 3 7 169 4 8 170 4 9 171 5 10 172 5 11 173 6 12 174 6 13 175 7 14 176 7 15 177 178 7 179 1 2 180 2 3 181 3 4 182 4 5 183 3 6 184 3 7 185 186 12 187 1 2 188 2 3 189 2 4 190 4 5 191 4 6 192 1 7 193 7 8 194 8 9 195 9 10 196 9 11 197 11 12 198 199 7 200 1 2 201 1 3 202 1 4 203 1 5 204 1 6 205 6 7 206 207 9 208 1 2 209 2 3 210 3 4 211 4 5 212 1 6 213 1 7 214 1 8 215 1 9 216 217 8 218 1 2 219 2 3 220 3 4 221 2 5 222 5 6 223 5 7 224 5 8 225 */
为了省去vis初始化
way1:
use father vex
way2:
vis[d]=1;
...
vis[d]=0;
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <iostream> 8 using namespace std; 9 #define ll long long 10 11 12 const double eps=1e-8; 13 const ll inf=1e9; 14 const ll mod=1e9+7; 15 const int maxn=2e5+10; 16 17 struct node 18 { 19 int d; 20 node *to; 21 }*e[maxn]; 22 23 char str[20]; 24 int siz[maxn],fa[maxn],link[maxn],cnt_link; 25 26 void dfs(int d) 27 { 28 node *p=e[d]; 29 siz[d]=1; 30 while (p) 31 { 32 if (fa[d]!=p->d) 33 { 34 fa[p->d]=d; 35 dfs(p->d); 36 siz[d]+=siz[p->d]; 37 } 38 p=p->to; 39 } 40 } 41 42 void findleaf(int d) 43 { 44 node *p; 45 int num; 46 cnt_link=0; 47 link[0]=d; 48 while (1) 49 { 50 p=e[d]; 51 num=0; 52 while (p) 53 { 54 if (fa[d]!=p->d) 55 { 56 if (siz[p->d]>siz[num]) 57 num=p->d; 58 } 59 p=p->to; 60 } 61 if (!num) 62 break; 63 link[++cnt_link]=num; 64 d=num; 65 } 66 } 67 68 int main() 69 { 70 node *p; 71 int n,x,y,i,root,dist,r,pos; 72 scanf("%d",&n); 73 for (i=1;i<n;i++) 74 { 75 scanf("%d%d",&x,&y); 76 p=new node(); 77 p->d=y; 78 p->to=e[x]; 79 e[x]=p; 80 81 p=new node(); 82 p->d=x; 83 p->to=e[y]; 84 e[y]=p; 85 } 86 gets(str); 87 88 printf("d %d\n",1); 89 fflush(stdout); 90 scanf("%d",&dist); 91 if (dist==0) 92 { 93 printf("! %d\n",1); 94 fflush(stdout); 95 return 0; 96 } 97 98 root=1; 99 while (1) 100 { 101 fa[root]=0; 102 dfs(root); 103 findleaf(root); 104 105 printf("d %d\n",link[cnt_link]); 106 fflush(stdout); 107 scanf("%d",&r); 108 if (r==0) 109 { 110 printf("! %d\n",link[cnt_link]); 111 fflush(stdout); 112 return 0; 113 } 114 115 pos=(dist+cnt_link-r)/2; 116 root=link[pos]; 117 dist=dist-pos; 118 if (dist==0) 119 { 120 printf("! %d\n",root); 121 fflush(stdout); 122 return 0; 123 } 124 125 printf("s %d\n",root); 126 fflush(stdout); 127 scanf("%d",&root); 128 dist--; 129 if (dist==0) 130 { 131 printf("! %d\n",root); 132 fflush(stdout); 133 return 0; 134 } 135 } 136 return 0; 137 } 138 /* 139 6 140 1 2 141 2 3 142 3 4 143 4 5 144 5 6 145 146 */
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <iostream> 8 using namespace std; 9 #define ll long long 10 11 12 const double eps=1e-8; 13 const ll inf=1e9; 14 const ll mod=1e9+7; 15 const int maxn=2e5+10; 16 17 struct node 18 { 19 int d; 20 node *to; 21 }*e[maxn]; 22 23 char str[20]; 24 int siz[maxn],fa[maxn],link[maxn],cnt_link; 25 bool vis[maxn]; 26 27 void dfs(int d) 28 { 29 node *p=e[d]; 30 vis[d]=1; 31 siz[d]=1; 32 while (p) 33 { 34 if (!vis[p->d]) 35 { 36 dfs(p->d); 37 siz[d]+=siz[p->d]; 38 fa[p->d]=d; 39 } 40 p=p->to; 41 } 42 vis[d]=0; 43 } 44 45 void findleaf(int d) 46 { 47 node *p; 48 int num; 49 cnt_link=0; 50 link[0]=d; 51 while (1) 52 { 53 p=e[d]; 54 num=0; 55 while (p) 56 { 57 if (fa[d]!=p->d) 58 { 59 if (siz[p->d]>siz[num]) 60 num=p->d; 61 } 62 p=p->to; 63 } 64 if (!num) 65 break; 66 link[++cnt_link]=num; 67 d=num; 68 } 69 } 70 71 int main() 72 { 73 node *p; 74 int n,x,y,i,root,dist,r,pos; 75 scanf("%d",&n); 76 for (i=1;i<n;i++) 77 { 78 scanf("%d%d",&x,&y); 79 p=new node(); 80 p->d=y; 81 p->to=e[x]; 82 e[x]=p; 83 84 p=new node(); 85 p->d=x; 86 p->to=e[y]; 87 e[y]=p; 88 } 89 gets(str); 90 91 printf("d %d\n",1); 92 fflush(stdout); 93 scanf("%d",&dist); 94 if (dist==0) 95 { 96 printf("! %d\n",1); 97 fflush(stdout); 98 return 0; 99 } 100 101 root=1; 102 while (1) 103 { 104 // memset(vis,0,sizeof(vis)); 105 fa[root]=0; 106 dfs(root); 107 findleaf(root); 108 109 printf("d %d\n",link[cnt_link]); 110 fflush(stdout); 111 scanf("%d",&r); 112 if (r==0) 113 { 114 printf("! %d\n",link[cnt_link]); 115 fflush(stdout); 116 return 0; 117 } 118 119 pos=(dist+cnt_link-r)/2; 120 root=link[pos]; 121 dist=dist-pos; 122 if (dist==0) 123 { 124 printf("! %d\n",root); 125 fflush(stdout); 126 return 0; 127 } 128 129 printf("s %d\n",root); 130 fflush(stdout); 131 scanf("%d",&root); 132 dist--; 133 if (dist==0) 134 { 135 printf("! %d\n",root); 136 fflush(stdout); 137 return 0; 138 } 139 } 140 return 0; 141 } 142 /* 143 6 144 1 2 145 2 3 146 3 4 147 4 5 148 5 6 149 150 */