题目链接
题意简述
有
n
−
1
n-1
n−1 个评委分别为
A
A
A,
B
B
B 两个人打分,记为
a
1
,
a
2
,
⋯
,
a
n
−
1
a_1, a_2, \cdots, a_{n-1}
a1,a2,⋯,an−1 与
b
1
,
b
2
,
⋯
,
b
n
−
1
b_1, b_2, \cdots, b_{n-1}
b1,b2,⋯,bn−1,所有评委打分范围不得超出
[
1
,
h
]
[1,h]
[1,h]。由于第
n
n
n 名评委和
A
A
A 个关系很好,所以他希望
A
A
A 能赢
B
B
B。记分规则为删除
s
s
s 个最高分,删除
t
t
t 个最低分,其余的取平均分。如果无论评委如何操作
A
A
A 都的最终得分都无法严格大于
B
B
B 的最终得分,输出 "IMPOSSIBLE"
,否则,在保证
A
A
A 能赢
B
B
B 的前提下,我们需要最小化差值
a
n
−
b
n
a_n-b_n
an−bn,并输出这个差值。(“为了不让作弊看起来那么明显”)
输入描述
第一行包含一个整数 T ( T ≤ 12000 ) T(T\leq 12000) T(T≤12000),表示测试数据的组数。
每组数据的第一行包含四个整数 n , s , t , h ( 1 ≤ n ≤ 1 0 5 , 0 ≤ s , t ≤ n − 1 , 1 ≤ h ≤ 1 0 9 ) n, s, t, h\;(1\leq n\leq 10^5, 0\leq s,t\leq n-1, 1\leq h\leq 10^9) n,s,t,h(1≤n≤105,0≤s,t≤n−1,1≤h≤109)。数据保证 s + t ≤ n − 1 s + t \leq n-1 s+t≤n−1。
第二行包含 n − 1 n-1 n−1 个整数表示, a 1 , ⋯ , a n − 1 a_1, \cdots, a_{n-1} a1,⋯,an−1。
第三行包含 n − 1 n-1 n−1 个整数表示, b 1 , ⋯ , b n − 1 b_1, \cdots, b_{n-1} b1,⋯,bn−1。
数据保证 ∑ n ≤ 1 0 6 \sum n\leq 10^6 ∑n≤106。
解题思路
为了避免混淆,下文中的 n n n 表示已知评分的评委数,当前评委编号为 n + 1 n+1 n+1。
对 { a i } \{a_i\} {ai} 和 { b i } \{b_i\} {bi} 分别从小到大排序。由于我们要删除 s s s 个最高分,删除 t t t 个最低分,因此我们能够说明,无论最后一名评委如何给分, { a i } \{a_i\} {ai} 和 { b i } \{b_i\} {bi} 这两个数列的前 t − 1 t-1 t−1 个元素和后 s − 1 s-1 s−1 个元素一定是没有用的,下标从 t + 1 ∼ n − s t+1\sim n-s t+1∼n−s 范围内是一定不会被删去的,而 a t a_t at 与 a n − s + 1 a_{n-s+1} an−s+1 可能被删除可能不被删除,这取决于 a n + 1 a_{n+1} an+1 的选取。( b t b_t bt 与 b n − s + 1 b_{n-s+1} bn−s+1 同理,取决于 b n b_n bn 的值)
当 a n + 1 < a t a_{n+1} < a_t an+1<at 时,最后 a t a_t at 不被删除,而 a n − s + 1 a_{n-s+1} an−s+1 被删除, a t a_t at 对答案造成贡献。当 a n + 1 ∈ [ a t , a n − s + 1 ] a_{n+1}\in[a_t, a_{n-s+1}] an+1∈[at,an−s+1] 时, a n + 1 a_{n+1} an+1 对答案造成贡献。当 a t > a n − s + 1 a_t > a_{n-s+1} at>an−s+1 时, a n − s + 1 a_{n-s+1} an−s+1 对答案造成贡献。不过当 a n + 1 > a n − s + 1 a_{n+1}>a_{n-s+1} an+1>an−s+1 时,不如直接取 a n + 1 = a n − s + 1 a_{n+1}=a_{n-s+1} an+1=an−s+1,反正都是 a n − s + 1 a_{n-s+1} an−s+1 造成贡献, a n + 1 a_{n+1} an+1 取得小一点更可能让 a n + 1 − b n + 1 a_{n+1}-b_{n+1} an+1−bn+1 最小。当 a n + 1 < a t a_{n+1}<a_t an+1<at 时也是如此,直接令 a n + 1 = 1 a_{n+1}=1 an+1=1 即可。
因此最后答案所对应的 ( a n + 1 , b n + 1 ) (a_{n+1}, b_{n+1}) (an+1,bn+1) 一定有, a n ∈ 1 ∪ [ a t , a n − s + 1 ] a_n\in{1}\cup[a_t, a_{n-s+1}] an∈1∪[at,an−s+1],同理一定有 b n + 1 ∈ [ b t , b n − s + 1 ] ∪ h b_{n+1}\in[b_t, b_{n-s+1}]\cup{h} bn+1∈[bt,bn−s+1]∪h 中,分四种情况讨论即可。
还有一些细节,就是对于
s
=
0
s=0
s=0 以及
t
=
0
t=0
t=0 的情况需要特判处理,不过如果在
{
a
i
}
,
{
b
i
}
\{a_i\}, \{b_i\}
{ai},{bi} 分别添加两个元素
1
,
h
1, h
1,h,这样再令 s++, t++
,我们能够说明,答案一定不发生改变,从而巧妙地避开
s
=
0
s=0
s=0 以及
t
=
0
t=0
t=0 的情况。
S u m A + a c > S u m B + b c ⇔ S u m A + a c ≥ S u m B + b c + 1 SumA+a_c>SumB+b_c\Leftrightarrow SumA+a_c\geq SumB+b_c+1 SumA+ac>SumB+bc⇔SumA+ac≥SumB+bc+1
换言之:
a c − b c ≥ S u m B − S u m A + 1 a_c-b_c\geq SumB-SumA+1 ac−bc≥SumB−SumA+1
其中 a c a_c ac 是 { a t , a n + 1 , a n − s + 1 } \{a_t, a_{n+1}, a_{n-s+1}\} {at,an+1,an−s+1} 的中位数, b c b_c bc 是 { b t , b n + 1 , b n − s + 1 } \{b_t, b_{n+1}, b_{n-s+1}\} {bt,bn+1,bn−s+1} 的中位数。
代码实现
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 100000 + 10;
const long long inf = 0x7f7f7f7f7f7f7f7fLL;
int A[maxn], B[maxn]; /// 记录评委的评分
int main() {
int T; scanf("%d", &T);
while(T --) {
int n, s, t, h; scanf("%d%d%d%d", &n, &s, &t, &h);
for(int i = 1; i <= n-1; i ++) scanf("%d", &A[i]);
for(int i = 1; i <= n-1; i ++) scanf("%d", &B[i]);
A[n] = 1; A[n+1] = h;
B[n] = 1; B[n+1] = h;
n ++; s ++; t ++; /// n 表示序列中的总元素数
sort(A + 1, A + n + 1);
sort(B + 1, B + n + 1);
long long SumA = 0, SumB = 0; /// 记录一定会被统计到答案中的部分
for(int i = t + 1; i <= n - s; i ++) {
SumA += A[i];
SumB += B[i];
}
long long ans = inf;
/// 第一种情况 A_{n+1} = {1}, B_{n+1} in [B_t, B_{n-s+1}]
long long Btmp = A[t] + SumA - SumB - 1; /// 此时有 B_{n+1} <= Btmp
//printf("SumA = %lld, SumB = %lld, A:(%d, %d), B:(%d, %d)\n", SumA, SumB, A[t], A[n-s+1], B[t], B[n-s+1]);
if(Btmp >= B[t]) {
long long Bt = min(Btmp, (long long)B[n-s+1]);
ans = min(ans, 1 - Bt);
}
/// 第二种情况 A_{n+1} in [A_t, A_{n-s+1}], B_{n+1} = h
long long Atmp = B[n-s+1] + SumB - SumA + 1; /// 此时有 A_{n+1} >= Atmp
if(Atmp <= A[n-s+1]) {
long long At = max((long long)A[t], Atmp);
ans = min(ans, At - h);
}
/// 第三种情况 A_{n+1} = 1, B_{n+1} = h
if(A[t] - B[n-s+1] >= SumB - SumA + 1) {
ans = min(ans, 1ll - h);
}
/// 第四种情况 A_{n+1} in [A_t, A_{n-s+1}], B_{n+1} in [B_t, B_{n-s+1}]
if(A[n-s+1] - B[t] >= SumB - SumA + 1) {
ans = min(ans, max(SumB - SumA + 1, (long long)A[t] - B[n-s+1]));
}
ans == inf ? puts("IMPOSSIBLE") : printf("%lld\n", ans);
}
return 0;
}
我是废物,因为 "IMPOSSIBLE"
写成了 "Impossible"
而调试了好久 …