【ICPC】2020南京站 L. Let's Play Curling | 排序、set

133 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第28天,点击查看活动详情

【ICPC】2020南京站 L. Let's Play Curling | 排序、set

题目链接

Problem - L - Codeforces

题目

image.png

题目大意

红队和蓝队玩冰球。

游戏结束后,数轴上有 nn 个红色冰球分别位于数轴上的 a1,a2,...,ana_1,a_2,...,a_n 点,有 mm 个蓝色冰球分别位于数轴上的 b1,b2,...,bmb_1,b_2,...,b_m 点。如果球门位于 cc 点,那么红队得到的积分是满足以下要求的红球的数量:

  • 该球与球门的距离小于所有蓝球到球门的距离。

即满足红队的得分是满足条件 aic<minj=1mbjc|a_i-c|<\min_{j=1}^m|b_j-c|1in1\le i \le nii 的数量。

现在我们不知道球门的具体位置,试求红队可能取得的最高分是多少。如果红队可能取得的最高分是 00,就输出 Impossible

多组数据。

思路

我们把红球和蓝球都标注在数轴上。容易只需将球门放在发现连续的一段红球覆盖的区间的中点上,这连续的一段红球就都可以对答案产生贡献。

image.png

容易发现一段红球中如果有蓝球,那么他们不可能同时对答案产生贡献。

首先如果一个红球和一个蓝球重合,那么该位置的红球一定不会对答案产生贡献。为了便于统计连续红球的数量,我们直接把和蓝球在同一个坐标的红球删去。用 STL 里的容器 set 可以轻松实现该功能。

然后把所有球放在一起排序,坐标从小到大遍历所有球,遇见蓝球计数器清空,遇见红球计数器加一即可。每次修改计数器的值后更新答案。

代码

#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <iostream>
#include <math.h>
#include <map>
#include <set>
#include <queue>
#include <vector>
#include <stdlib.h>
#include <time.h>
using namespace std;
using LL=long long;
const int N=1e6+5;
const LL mod=1e9+7;
struct asdf{
	int val,typ;
}x[N];
int n,m,k,a[N];
set<int> v;
bool cmp(asdf a,asdf b)
{
	return a.val<b.val;
}
LL solve()
{
	v.clear();
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;++i) scanf("%d",&a[i]);
	for (int i=1;i<=m;++i)
	{
		scanf("%d",&x[i].val);
		x[i].typ=2;
		v.insert(x[i].val);
	}
	for (int i=1;i<=n;++i)
	{
		if (v.count(a[i])) continue;
		x[++m]={a[i],1};
	}
	sort(x+1,x+1+m,cmp);
	int ans=0,cnt=0;
	for (int i=1;i<=m;++i)
	{		
		if (x[i].typ==1) cnt++;
		else cnt=0;
		ans=max(ans,cnt);
	}
	if (ans==0) printf("Impossible\n");
	else printf("%d\n",ans);
	return 0;
}
int main()
{
	int T=1;
	scanf("%d",&T);

	while (T--) solve();
	return 0;
}