Codeforces Round 746 (Div. 2)
摘要
A,B,C(异或,边分治)
Powered by:NEFU AB-IN
Codeforces Round #746 (Div. 2)
A.Gamer Hemose
-
题意
问几轮打完怪
-
思路
取最大的和第二大的即可
-
代码
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/*
* @Author: NEFU AB-IN
* @Date: 2021-10-03 22:34:40
* @FilePath: \ACM\CF\2021.10.3.div2\a.cpp
* @LastEditTime: 2021-10-04 19:00:30
*/
using namespace std;
typedef pair<int, int> PII;
const int INF = 0x3f3f3f3f;
const int N = 1e6 + 10;
LL a[N];
void solve()
{
LL n, H;
cin >> n >> H;
for (int i = 1; i <= n; ++i)
{
cin >> a[i];
}
sort(a + 1, a + 1 + n, greater<LL>());
LL ans = 0;
LL tmp = a[1] + a[2];
if (H <= a[1])
{
cout << "1\n";
}
else if (H <= tmp)
{
cout << "2\n";
}
else
{
int tt = H / tmp;
if (H % tmp == 0)
cout << tt * 2 << '\n';
else if (H - tt * tmp > a[1])
cout << tt * 2 + 2 << '\n';
else if (H - tt * tmp <= a[1])
cout << tt * 2 + 1 << '\n';
}
}
signed main()
{
IOS;
int t;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
B. Hemose Shopping
-
题意
数组经过特定的调换(即下标之差大于)后,能否升序?
-
思路
判断中间不能动的与升序的位置是否对应即可
-
代码
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/*
* @Author: NEFU AB-IN
* @Date: 2021-10-03 22:34:47
* @FilePath: \ACM\CF\2021.10.3.div2\b.cpp
* @LastEditTime: 2021-10-03 23:38:24
*/
using namespace std;
typedef pair<int, int> PII;
const int INF = 0x3f3f3f3f;
const int N = 1e6 + 10;
int a[N], b[N];
void solve()
{
int n, x, flag = 0;
cin >> n >> x;
for (int i = 1; i <= n; ++i)
{
cin >> a[i];
if (a[i] < a[i - 1])
flag = 1;
b[i] = a[i];
}
sort(b + 1, b + 1 + n);
if (!flag)
{
cout << "YES\n";
return;
}
for (int i = 1; i <= n; ++i)
{
if (i - 1 < x && n - i < x && a[i] != b[i])
{
cout << "NO\n";
return;
}
}
cout << "YES\n";
return;
}
signed main()
{
IOS;
int t;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
C.Bakry and Partitioning
-
题意
存在一个节点数为的最小生成树,每个点都有点值,问最少剪一条边,最多剪条边,问是否剩下的连通块的异或和均相等
-
思路
分类讨论
- 如果总异或为,说明一定可以剪成两个连通块进行异或结果为,也就是结果相等
- 如果总异或不为
- 既然要各连通块异或和相等,而且如果把边都连起来,异或还等于总异或和,那么最优的情况就是,让每个连通块的异或和都等于总异或和,并且连通块的数量为大于1的奇数,这样符合情况并最优
- 如果连通块的个数是偶数的话,那么合起来的异或和不可能等于总异或和,是不成立的
-
代码
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101/*
* @Author: NEFU AB-IN
* @Date: 2021-10-03 23:55:53
* @FilePath: \ACM\CF\2021.10.3.div2\c.cpp
* @LastEditTime: 2021-10-07 19:36:13
*/
using namespace std;
typedef pair<int, int> PII;
const int INF = 0x3f3f3f3f;
const int N = 1e6 + 10;
int a[N];
struct Edge
{
int v, ne;
} e[N << 2];
int h[N];
int cnt, ans, sum;
void add(int u, int v)
{
e[cnt].v = v;
e[cnt].ne = h[u];
h[u] = cnt++;
}
void init()
{
memset(h, -1, sizeof(h));
cnt = 0;
ans = 0;
sum = 0;
}
int dfs(int u, int fa)
{
int tmp = a[u];
for (int i = h[u]; ~i; i = e[i].ne)
{
int v = e[i].v;
if (fa == v)
continue;
tmp ^= dfs(v, u);
}
if (tmp == sum)
{
ans++;
return 0;
}
return tmp;
}
void solve()
{
init();
int n, k;
scanf("%d%d", &n, &k);
for (int i = 1; i <= n; ++i)
{
scanf("%d", &a[i]);
sum ^= a[i];
}
int u, v;
for (int i = 1; i < n; ++i)
{
scanf("%d%d", &u, &v);
add(u, v);
add(v, u);
}
if (!sum)
{
printf("YES\n");
return;
}
dfs(1, 0);
if (k >= 3 && ans >= 3)
{
printf("YES\n");
}
else
{
printf("NO\n");
}
}
signed main()
{
int t;
scanf("%d", &t);
while (t--)
{
solve();
}
return 0;
}