待补题,题目传送门

# A

超级无敌水题
找是否有至少、连续三个相等

c++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void solve () {
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i];

for (int i = 1; i <= n - 2; i++) {
if (a[i] == a[i + 1] && a[i] == a[i + 2]) {
cout << "Yes" << endl;
return;
}
}

cout << "No" << endl;
}

# B

的水题

c++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void solve () {
int q;
cin >> q;
stack<int> s;

for (int i = 1; i <= 100; i++)
s.push(0);

while (q--) {
int op, x;
cin >> op;

if (op == 2) {
cout << s.top() << endl;
s.pop();
}
else {
cin >> x;
s.push(x);
}
}
}

# C

昏迷睡觉题目

# 题目大意

给定两个序列,分别有:nn 个数和 mm 个数
你可以从两个序列中取出若干个数,但是,在第一个序列取的数的个数必须大于等于在第二个序列中取的
问:总和最大是多少

# 解题思路

其实这题很简单,就是贪贪贪,把两个数列升序排列后,能取数只剩下这几种情况

  • a[i] >= 0 && b[i] >= 0 :肯定是都取
  • a[i] >= 0 && b[i] <= 0 :此时只取 aia_i
  • a[i] <= 0 && b[i] >= 0a[i] + b[i] >= 0bb 数组弥补了 aa 数组负数的情况,那么也可以都取,总值还是增加的

但是一开始写的代码写抽象了,WA\color{red}{WA} 了两个点

c++
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
int n, m, a[N], b[N];

bool cmp(int x, int y) {
return x > y;
}

void solve () {
cin >> n >> m;
for (int i = 1; i <= n; i++)
cin >> a[i];
for (int i = 1; i <= m; i++)
cin >> b[i];

sort(a + 1, a + n + 1, cmp), sort(b + 1, b + m + 1, cmp);

int res = 0, idx = 0;
while (a[idx] >= 0 && idx <= n)
res += a[idx++];
idx--;

int idxx = 0;
while (idxx <= m) {
if (idxx <= idx) {
if (b[idxx] >= 0)
res += b[idxx];
else
break;
}
else {
if (b[idxx] + a[idxx] >= 0)
res += (b[idxx] + a[idxx]);
else
break;
}
idxx++;
}

cout << res << endl;
}

改进后,可以变成 O(NlogN)O(N · \log N) 的复杂度

c++
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
int n, m, a[N], b[N];

bool cmp(int x, int y) {
return x > y;
}

void solve () {
cin >> n >> m;
for (int i = 1; i <= n; i++)
cin >> a[i];
for (int i = 1; i <= m; i++)
cin >> b[i];

sort(a + 1, a + n + 1, cmp), sort(b + 1, b + m + 1, cmp);

int res = 0;

for (int i = 1; i <= n; i++) {
int t = 0;

if (a[i] >= 0 && b[i] >= 0)
t = a[i] + b[i];
else if (a[i] >= 0 && b[i] <= 0)
t = a[i];
else if (a[i] <= 0 && b[i] >= 0 && b[i] + a[i] >= 0)
t = a[i] + b[i];
else
break;

if (t >= 0)
res += t;
}

cout << res << endl;
}

# D

# 题目大意

给定无向图,每条边有一个值 wiw_i,求从 11 点到 nn 点的所有路径中,所有边权异或值最小的是?

  • 2N2 \le {N} \le
  • N1MN(N1)2N-1 \le {M} \le {\frac{N(N-1)}{2}}
  • 1ui<vi1 \le {u_i} < {v_i} \le
  • 0wi<2600 \le {w_i} < {2^{60}}

# 错解

想着类似最短路,于是想着用 DijkstraDijkstra,但是寄了

c++
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
int n, m, graph[20][20], d[20];
bool st[20];

void solve () {
cin >> n >> m;
for (int i = 1; i <= n; i++) {
d[i] = 1e18;
for (int j = 1; j <= n; j++)
graph[i][j] = 1e18;
}

for (int i = 1, u, v, w; i <= m; i++) {
cin >> u >> v >> w;
graph[u][v] = graph[v][u] = w;
}

d[1] = 0;

while (true) {
int t = -1;
for (int i = 1; i <= n; i++)
if (!st[i] && (t == -1 || d[i] < d[t]))
t = i;

if (t == -1)
break;

st[t] = -1;

for (int i = 1; i <= n; i++) {
if (!st[i])
d[i] = min(d[i], d[t] ^ graph[t][i]);
}
}

cout << d[n] << endl;
}

# 正解

观察到,数据范围极小,为什么不用搜索呢?

c++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int n, m;
bool st[20];
vector<PII> graph[14];

// 1e18 还不够,得开 LONG_LONG_MAX
int ans = LONG_LONG_MAX;

void dfs(int u, int res) {
if (u == n) {
ans = min(ans, res);
return;
}

for (auto t : graph[u]) {
int v = t.first, w = t.second;

if (st[v])
continue;

st[v] = 1;
dfs(v, res ^ w);
st[v] = 0;
}
}

有一个细节需要注意,1e181e{18} 还是不够大,得用 LONG_LONG_MAX

# E

# 题目大意

给定两个整数 n,mn,m 和三个长度为 mm 的整数序列 X=(x1,...,xm),Y=(y1,...,ym),Z=(z1,...,zm)X=(x_1,...,x_m),~Y=(y_1,...,y_m),~Z=(z_1,...,z_m)
请你构造一个长度为 nnAA 序列,满足对 i[1,m]{i} \in {[1,m]} 均有,AxiXORAyi=xiA_{x_i}~XOR~A_{y_i} = x_i
找出满足这样性质的,i=1nAi\sum\limits_{i=1}^{n} A_i 最小的序列

# 题解

有丶难了,传送门

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

duoxichangan 微信支付

微信支付

duoxichangan 支付宝

支付宝