HDU 7075 Unfair contest

题目链接

HDU 7075 传送门

题意简述

n − 1 n-1 n1 个评委分别为 A A A, B B B 两个人打分,记为 a 1 , a 2 , ⋯   , a n − 1 a_1, a_2, \cdots, a_{n-1} a1,a2,,an1 b 1 , b 2 , ⋯   , b n − 1 b_1, b_2, \cdots, b_{n-1} b1,b2,,bn1,所有评委打分范围不得超出 [ 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 anbn,并输出这个差值。(“为了不让作弊看起来那么明显”)

输入描述

第一行包含一个整数 T ( T ≤ 12000 ) T(T\leq 12000) T(T12000),表示测试数据的组数。

每组数据的第一行包含四个整数 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(1n105,0s,tn1,1h109)。数据保证 s + t ≤ n − 1 s + t \leq n-1 s+tn1

第二行包含 n − 1 n-1 n1 个整数表示, a 1 , ⋯   , a n − 1 a_1, \cdots, a_{n-1} a1,,an1

第三行包含 n − 1 n-1 n1 个整数表示, b 1 , ⋯   , b n − 1 b_1, \cdots, b_{n-1} b1,,bn1

数据保证 ∑ n ≤ 1 0 6 \sum n\leq 10^6 n106

解题思路

为了避免混淆,下文中的 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 t1 个元素和后 s − 1 s-1 s1 个元素一定是没有用的,下标从 t + 1 ∼ n − s t+1\sim n-s t+1ns 范围内是一定不会被删去的,而 a t a_t at a n − s + 1 a_{n-s+1} ans+1 可能被删除可能不被删除,这取决于 a n + 1 a_{n+1} an+1 的选取。( b t b_t bt b n − s + 1 b_{n-s+1} bns+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} ans+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,ans+1] 时, a n + 1 a_{n+1} an+1 对答案造成贡献。当 a t > a n − s + 1 a_t > a_{n-s+1} at>ans+1 时, a n − s + 1 a_{n-s+1} ans+1 对答案造成贡献。不过当 a n + 1 > a n − s + 1 a_{n+1}>a_{n-s+1} an+1>ans+1 时,不如直接取 a n + 1 = a n − s + 1 a_{n+1}=a_{n-s+1} an+1=ans+1,反正都是 a n − s + 1 a_{n-s+1} ans+1 造成贡献, a n + 1 a_{n+1} an+1 取得小一点更可能让 a n + 1 − b n + 1 a_{n+1}-b_{n+1} an+1bn+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}] an1[at,ans+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,bns+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+bcSumA+acSumB+bc+1

换言之:

a c − b c ≥ S u m B − S u m A + 1 a_c-b_c\geq SumB-SumA+1 acbcSumBSumA+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,ans+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,bns+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" 而调试了好久 …

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值