1928_B. Equalize_排序_去重_双指针_滑动窗口_贪心

#include

using namespace std;

void solve()
{
	int n;
	cin>>n;
	vector<int> a;
	for(int i=0;i<n;i++)
	{
		int x;
		cin>>x;
		a.push_back(x);
	}
	sort(a.begin(),a.end());
	a.erase(unique(a.begin(),a.end()),a.end());
	
	int ans=0;
	int len=a.size();
	for(int i=0,j=0;i<len;i++)
	{
		while(j<=i&&(a[i]+1-a[j])>n)
			j++;
		ans=max(ans,i-j+1);
	}
	cout<<ans<<endl;
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
	int t;
	cin>>t;
	
	while(t--)
		solve();
	
	return 0;
}

改成下面这样输入更简洁,但是需要初始化 vector 的大小

#include

using namespace std;

void solve()
{
	int n;
	cin>>n;
	vector<int> a(n);
	for(auto& e:a)
		cin>>e;
	sort(a.begin(),a.end());
	a.erase(unique(a.begin(),a.end()),a.end());
	
	int ans=0;
	int len=a.size();
	for(int i=0,j=0;i<len;i++)
	{
		while(j<=i&&(a[i]+1-a[j])>n)
			j++;
		ans=max(ans,i-j+1);
	}
	cout<<ans<<endl;
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
	int t;
	cin>>t;
	
	while(t--)
		solve();
	
	return 0;
}

该题是 div 2 的 B 题,赛时我没有写出来,没有分析出来性质

我以为是差分之类的,但是差分只可以处理两个数字之间的,后面又以为是并查集,以为是看后面的数字和第一个数字的关系,类似于并查集的和根节点之间的关系,两个数之间的差距只要在 n-1 这个范围内就是可操作为相等的两个数字

排序之后来做

两个数字原本相等的话,经过操作之后一定不相等,因为一个排列里面没有两个相等的数字,所以需要把原来数组里面的重复数字去掉

去掉之后可以用双指针算法(或者说滑动窗口来做)

i 指针遍历所有元素,作为右端点,j 指针作为左端点,在两个端点之间的元素都是相等的,我们的目标是找到最长的区间长度,左端点更新的条件是,右端点和左端点的差值严格大于 n-1 ,超过了能修改的最大值

贪心的维护一个最大值,就是最后的答案

很快的写出前面两题有 1454 的表现分,我第一题其实写的飞快,速度很快也可以上大分

我写出来第一题的表现分是 1006

双指针算法在前面的题比较常见,感觉遇到过很多次了,另外有一个经验是,排序之后更加方便分析问题

我现在想上分,快速的分析出做法并快速的敲出来非常重要,估计 div 2 写出来前面两题,手速比较快我就可以绿名了

主要还是要多写题,这是唯一的救赎之道

你可能感兴趣的:(全集,#,CF,div,2,B,题,算法,数据结构)