补题链接
神秘第一场网络赛之前的最后一场 VP。
签到题交了 4 发才过尽显菜鸡本色,为后面的网络赛窜稀埋下伏笔。
D. Operator Precedence
队友写的。
找到一个长度为 $2n$ 的正整数列 $a$ 满足:
$$
\sum_{i=1}^n a_{2i-1}a_{2i}=a_1a_{2n}\prod_{i=2}^n(a_{2i-2}+a_{2i-1})\neq 0
$$我们只需要构造一个形如 $2,-1,2-,-1,\ldots,2,-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
| #include <bits/stdc++.h>
using namespace std;
int n;
void solve() {
cin>>n;
if(n==2){
cout<<"1 -3 -3 1";
return;
}
if(n==3){
cout<<"1 -10 6 6 -10 1";
return;
}
cout<<1<<' ';
for(int i=1;i<=(n*2-1)/2;i++){
cout<<"2 -1 ";
}
cout<<3-n;
}
signed main() {
cin.tie(nullptr)->sync_with_stdio(false);
int T;
cin>>T;
while(T--){
solve();
cout<<"\n";
}
return 0;
}
|
J. Mysterious Tree
交互题
给定一个节点个数为 $n$ 的星形树或者链状树,每次询问你可以给出一对点 $u, v$,返回你这两个点是否相连,让你在 $\lceil \frac{n}{2} \rceil + 3$ 次以内判断树的种类。
不难想到对于一个链状树来说,至多只能有两个点与其相连,所以我们枚举一遍 $(i, i + 1)$,若是星形树的话,至少会有一对成立。我们把这一对的 $u,v$ 分别和其他任意的点连边判断是否存在即可。特别注意的就是当 $n$ 为奇数时的情况。
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
| #include <bits/stdc++.h>
using namespace std;
bool ask(int u, int v) {
bool res = 0;
cout << "? " << u << " " << v << endl;
cin >> res;
return res;
}
void answer(int u) { cout << "! " << u << endl; }
void solve() {
int n;
cin >> n;
vector<pair<int, int>> vec;
vector<int> vis(n + 1);
for (int i = 1; i + 1 <= n; i += 2) {
if (ask(i, i + 1)) {
vec.emplace_back(i, i + 1);
vis[i] = vis[i + 1] = 1;
}
}
if (vec.size() > 1) {
answer(1);
return;
}
if (n % 2) {
int u = 1;
while (vis[u])
u++;
if (ask(n, u)) {
vec.emplace_back(n, u);
vis[n] = vis[u] = 1;
}
}
if (vec.size() != 1) {
answer(1);
return;
}
auto [u, v] = vec.front();
int p = 1;
while ((p == u or p == v) and p <= n)
p++;
int q = 1;
while ((q == p or q == u or q == v) and q <= n)
q++;
bool res1 = ask(u, p);
bool res2 = ask(v, p);
bool res3;
if (res1 == 0 and res2 == 0) {
answer(1);
return;
}
if (res1) {
res3 = ask(u, q);
}
if (res2) {
res3 = ask(v, q);
}
if (res3)
answer(2);
else
answer(1);
return;
}
signed main() {
cin.tie(nullptr)->sync_with_stdio(false);
int T = 1;
cin >> T;
while (T--)
solve();
return 0;
}
|
M. V-Diagram
给定一个 V 形的长度为 $n$ 的数组 $a$,满足从中间向两边递增,选择一个区间使得区间内的平均值最大。
众所周知,选择一个区间等效于从前面删除若干个数字和从后面删除若干个数字。
首先我们不难看出我们至多只能删除一边的数字,然后我们对每一边的情况模拟一下就行。
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
| #include <bits/stdc++.h>
using namespace std;
#define int long long
void solve() {
int n;
cin >> n;
vector<int> a(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
auto mit = min_element(a.begin(), a.end());
auto sumlft = accumulate(a.begin(), mit, 0ll);
auto sumrht = accumulate(next(mit), a.end(), 0ll);
double ans = -1;
if (1.0 * sumlft / (mit - a.begin()) - 1.0 * sumrht / (a.end() - next(mit)) > 1e-5) {
sumlft += *mit;
for (auto it = next(mit); it != a.end(); it++) {
sumlft += *it;
ans = max(ans, 1.0 * sumlft / (it - a.begin() + 1));
}
} else {
sumrht += *mit;
for (auto it = prev(mit); it - a.begin() >= 0; it--) {
sumrht += *it;
ans = max(ans, 1.0 * sumrht / (a.end() - it));
}
}
cout << fixed << setprecision(20) << ans << "\n";
}
signed main() {
cin.tie(nullptr)->sync_with_stdio(false);
int T = 1;
cin >> T;
while (T--)
solve();
return 0;
}
|