Roast:
看到公告里说 I tried my best to create some good problems and clear statements, so I hope you'll enjoy the round:)
和 story
然后在做题时候感觉自己的C假了。感慨weak data。然而还好没有$FST$。
很可惜的就是F题用了time
这个变量 $\textsf{CE}$ 了,不然绝杀了QwQ。。
我太菜了。
A - Shifting Stacks
Description
给定 $n$ 堆石头堆,第 $i$ 堆上面有 $h_i$ 块石头。现在可以进行多次操作,每次可以将第 $i$ 堆上面拿走一块石头放到第 $i+1$ 堆上面(别问能不能拿走最后一堆上面的),可以重复在某一堆上面拿,直到拿空。问能否在多次操作之后使得 $h_i$ 呈严格单调递增。$1\le n\le100,0\le h_i\le10^9$
Solution
观察发现:最小的且满足要求的数列,是 $0, 1, 2, \cdots, n-1 $。前缀和维护一下。
Code
1 | int n , a[maxn]; |
B - Eastern Exhibition
Description
给定 $n$ 个房子的坐标,第 $i$ 个房子的坐标为 $(x_i,y_i)$ 。(所有横纵坐标的值均为整数)
现在想要建一个剧院,该剧院到第 $i$ 个房子的曼哈顿距离为 $dist(x)$ ,请求出有多少个坐标,使得剧院建在这个坐标上面时,使得 $\sum_{i=1}^{n}dist(i)$ 最小?
$1\le n\le 1000,0\le x_i,y_i\le10^9$
Solution
每个维度不相关,中位数
问题,甚至可以多维度。
Code
1 | int x[maxn], y[maxn]; |
C2 - Guessing the Greatest (hard version)
Description
交互题。
已知一个长度为 $n$ 的数列 ${a_n}$ ,我们在一开始只知道数列的长度。
我们每次可以向系统询问一段区间 $[l,r]$ 内第二大元素的下标,现在我们需要经过多次询问,找出该数列中最大元素的下标。
询问次数不得超过 $20$ 次。
$2^{20}\ge 10^5$
Solution
观察到与值域没啥关系。
就考虑最大值区间在左边还是在右边。
trick : 第一次先询问一次中间,看最大值再左边还是右边。
接着 二分区间。
$2^{20} > 10^5$ 可以通过。
Code
1 | int32_t main() |
D - Max Median
Description
给定一个长度为 $n$ 的数列 ${a_n}$ ,尝试找出一组长度不短于 $k$ 的连续子数列,使得其中位数最大。
中位数的定义(和标准可能有所出入):长度为 N 的数列,其升序排列后的第 $\lfloor\frac{N+1}{2}\rfloor$ 个元素,为该数列的中位数。
$1\le k\le n\le 2\times10^5,1\le a_i\le n$
Solution
官方做法很好:
如果 ${a_n}$ 中只有 $0$ 和 $1$ ,咋选?
显然,应该选择一个长度不小于 $k$ 的区间段,使得其中 $0$ 的数量少于 $1$ ,这样才能使得中位数是 $1$ 而非 $0$ 。
我们也可以将 0 改为 −1 ,问题就变成了如何使区间和为正数了。
直接求区间和的最大值,那么我们直接枚举 $r$ ,然后找 $suml$ 最小值,然后相减一下,看看能不能使得区间值大于 0 的 。朴素复杂度 $O(n^2)$ ,数据结构优化 $O(n\ log_n)$ ,线性递推复杂度 $O(n)$。然而,现在这数列里面的数也不只 0 和 1 ?
我们可以抽象一下,0 和 1 是典型的布尔值,那么对于数列里面的每个数,我们可以对其进行一个布尔表达式的运算,使得结果为 0 或者 1 即可(也就是将数分成两类)。
题目要求中位数最大,那我们的表达式应该也和大小有关系。不妨设定一个数 $x$ ,如果 $ai\ge x$ 就将其标记为 1,反之标记为 0 。显然 $min{1\le i\le n}a_i\le x\le max{1\le i\le n}a_i$对于 $x$ 构造出来的新数列,如果我们可以找出一个中位数为 1 的子数列,说明这个子数列在原数列中的对应数列,他的中位数是不小于 $x$ 的。
对于这个 $x$,我们可以二分: 对中位数 $x$ 在值域上进行二分,每次线性判定,总复杂度 $O(nlogn)$Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25int n , k , a[maxn], sum[maxn];
int32_t main()
{
close;
cin >> n >> k;
for(int i = 1; i <= n; i++) cin >> a[i];
auto chk = [&](int x){
for(int i = 1; i <= n; i++){
sum[i] = sum[i-1] + (a[i] >= x ? 1 : -1);
}
int mn = INF, mx = -INF;
for(int i = k; i <= n; i++){
umin(mn, sum[i-k]), umax(mx, sum[i] - mn);
}
return mx > 0;
};
int l = 0, r = INF;
while(l < r){
int mid = (l+r+1) >> 1;
if(chk(mid)) l = mid;
else r = mid-1;
}
cout << l << endl;
return 0;
}
E - Paired Payment
Description
Solution
Code
1 |
F - Pairs of Paths
Description
Solution
有交的点对,按lca排序,先处理lca不同的(lca相同的直接C(size,2)就行了),不同的如果有交一定是lca深度大的再lca深度小的链上
时间复杂度$O(nlog^2)$
Code
1 | int n, m; |