2019 ICPC 徐州现场赛 复现

rank solved A B C D E F G H I J K L M
? 8 O . O . O O . O . O . O O

A

Solved by Henry.

C

Solved by Henry.

E

Solved by Henry.

F

Solved by Forsaken.

H

Solved by XLor and Forsaken.

假设 $[0,x]$ 能够构造,询问 $[0,x+1]$ 的权值和为 $S$,那么 $[0,S]$ 必能构造,且 $S$ 每次至少翻一倍。

套个树状数组套主席树,时间复杂度 $O(n\log^3n)$。

J

Solved by Henry.

如果 $n$ 是奇数,显然存在欧拉回路,截断欧拉回路就是答案。

如果 $n$ 是偶数,想先构造 $n/2$ 条路径,第i条路径连接 $2i-1$ 和 $2i$ 两个点,且路径的长度都要不同。
我选择 $i \bmod 2=1$ 时,路径长度为 $2i-1$ ,依次连接 $2i-1 \to 1 \to 2i \to 2 \to \dots \to 2i-1$ 然后直接连到 $2i$ , $i\bmod2=1$ 时,路径长度为 $2i-2$ ,依次连接 $2i-1 \to 1 \to 2i \to 2 \to \dots \to 2i$

显然,每条路径最多占用每个点2个度数,且每条边连接的点标号一定是$2i$或$2i-1$和一个小于$2i$的点, 保证不和之前连接的边重复。构造这样$n/2$条路径之后,剩下的所有点度数为偶数,跑欧拉回路切断得到剩下的答案。

L

Solved by XLor.

模板题。

M

Solved by XLor.

两棵树合并后的重心,在原来两个重心的路径上。

dfs,从下往上,重心往上爬。

代码

J

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include<bits/stdc++.h>
using namespace std;
const int N=1003;
int n;
bool vis[N][N];
int ans[N*N/2],cnt;
int tmpans[N][N];

void dfs(int x){
for(int i=1; i<=n; i++){
if(!vis[x][i]){
vis[x][i]=vis[i][x]=1;
dfs(i);
}
}
ans[cnt++]=x;
return;
}

int main(){
scanf("%d",&n);
for(int i=1; i<=n; i++) vis[i][i]=1;
if(n%2){
dfs(n);
int p=0;
for(int i=1; i<n; i++){
for(int j=0; j<i; j++)
printf("%d ",ans[p++]);
printf("%d\n",ans[p]);
}
}
else{
int p=1;
for(int i=1; i<n; i+=2){
for(int j=0; j<p; j++){
if(j%4==0) tmpans[p][j]=i;
else if(j%4==2) tmpans[p][j]=i+1;
else tmpans[p][j]=(j+1)/2;
}
tmpans[p][p]=i+1;
for(int j=0; j<p; j++){
vis[tmpans[p][j]][tmpans[p][j+1]]=1;
vis[tmpans[p][j+1]][tmpans[p][j]]=1;
}
if(p%4==1){
p++;
}
else{
p+=3;
}
}
dfs(n);
p=0;
for(int i=1; i<n; i++){
if(tmpans[i][0]){
for(int j=0; j<=i; j++){
printf("%d%c",tmpans[i][j],j==i?'\n':' ');
}
}
else{
for(int j=0; j<i; j++)
printf("%d ",ans[p++]);
printf("%d\n",ans[p]);
}
}
}
return 0;
}