题目描述
给出n 个点,每个点都有一个坐标xi,这些点中一些点是白点,另外的是黑点,求满足以下两个条件的最长的线段的长度
条件一:线段的左右端点都必须在给出的n 个点中
条件二:给出的n 个点中,被这条线段所包含的点中黑点个数必须等于白点个数(包括左右端点)
输入
第1 行:一个整数n
第2…n+1 行:每行一个整数xi,表示点的坐标,和一个字符(’G’ 表示黑点,’H’ 表示白点),中间用空格隔开,
输出
一行一个数,最长的线段的长度
样例输入
6
4 G
10 H
7 G
16 G
1 G
3 H
样例输出
7
数据范围限制
• 对于30% 的数据,n <= 10^3。
• 对于100% 的数据,n <= 10^5,1 <= xi <= 10^9。
思路:
这道题主要是求哪点到哪点,在黑白点数量相同的情况下的最远距离。会用到前缀和。我们可以用两个相反数来表示,如果相加起来的前缀和相同,那么黑点白点的数量一定相等。我们可以用一个数组是否为零来判断当前前缀和和之前的是否相同,如果相同,就在判断数组上标上当前点的位置,如果不同,就用当前点的位置减去之前点的位置,可以用一个数组来记录。
AC代码:
#include<bits/stdc++.h> // 包含标准库头文件
using namespace std; // 使用标准命名空间
struct node // 定义点的结构体
{
int a,b; // a存储坐标,b存储点的类型值(G为-11,H为11)
}m[100005]; // 定义点数组,最大容量100005
int n,ans; // n存储点数,ans存储最终结果
int f[5],jl[1000005]; // f数组用于前缀和计算,jl数组记录第一次出现某个前缀和的位置
char c; // 临时存储点类型字符
int cmp(node x,node y) // 比较函数,用于排序
{
return x.a<y.a; // 按坐标升序排列
}
int main()
{
scanf("%d",&n); // 读取点数n
for(int i=1;i<=n;i++) // 循环读取每个点
{
cin>>c; // 读取点类型字符
scanf("%d",&m[i].a); // 读取点坐标
if(c=='G') // 如果是黑点
{
m[i].b=-1; // 赋值为-1
}
else // 如果是白点
{
m[i].b=1; // 赋值为1
}
}
sort(m+1,m+n+1,cmp); // 将所有点按坐标排序
for(int i=1;i<=n;i++) // 遍历排序后的点
{
// 计算前缀和,使用i%2实现滚动数组优化
f[i%2]=f[(i+1)%2]+m[i].b;
if(jl[f[i%2]]==0) // 如果该前缀和第一次出现
{
jl[f[i%2]]=m[i].a; // 记录该前缀和对应的坐标
}
else // 如果该前缀和之前出现过
{
// 计算当前坐标与第一次出现该前缀和时的坐标差,更新最大值
ans=max(ans,m[i].a-m[jl[f[i%2]]].a);
}
}
printf("%d",ans); // 输出结果
return 0; // 程序结束
}
206

被折叠的 条评论
为什么被折叠?



