社区讨论

代码求调(有思路)

CF2171FRae Taylor and Trees (hard version)参与者 3已保存回复 3

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
3 条
当前快照
1 份
快照标识符
@mk192erh
此快照首次捕获于
2026/01/05 22:22
上个月
此快照最后确认于
2026/01/09 16:25
上个月
查看原帖
考虑把一段递增序列合并,最后一定是若干个递增序列.
然后考虑这几个集合能否合并:
先确定每个集合的最小值和最大值
那么能否合并的关键在于:这个集合的最大值是否大于前面的最小值
玄关,thx.
CPP
#include<bits/stdc++.h>
using namespace std;

const int maxn=2e5+10;
int T;
int n;
int a[maxn];
struct node{
	int maxx,minn;
	vector<int>id; // 记录集合里面有哪些元素
}s[maxn];
int cnt;
int minn_id[maxn]; // 前缀最小值所在的下标

int main()
{
	cin>>T;
	while(T--)
	{
		cin>>n;
		for(int i=1;i<=n;i++)
			cin>>a[i];

		for(int i=1;i<=cnt;i++)
			s[i].id.clear();	
		cnt=1;
		s[1].id.push_back(1);
		s[1].maxx=s[1].minn=a[1];
		minn_id[1]=1;

		for(int i=2;i<=n;i++)
		{
			if(a[i]>a[i-1]) // 合并到现在的集合中
				s[cnt].maxx=a[i],s[cnt].id.push_back(i);
			else // 新起一个集合
			{
				cnt++;
				s[cnt].id.push_back(i);
				s[cnt].maxx=a[i];
				s[cnt].minn=a[i];
				// 考虑这个集合是否会改变前缀最小值
				if(a[i]<a[minn_id[cnt-1]])
					minn_id[cnt]=i;
				else
					minn_id[cnt]=minn_id[cnt-1];
			}
		}
		/*puts("Sets:");
		for(int i=1;i<=cnt;i++)
		{
			cout<<i<<':';
			for(int j=0;j<s[i].id.size();j++)
				cout<<s[i].id[j]<<' ';
			cout<<'\n';
		}*/
		if(cnt==1) // 只有一个集合,那全部人都和第一个连边就行
		{
			puts("Yes");
			for(int i=1;i<s[1].id.size();i++)
				cout<<a[s[1].id[0]]<<' '<<a[s[1].id[i]]<<'\n';
		}
		else // 判断能否合并
		{
			bool flag=1;
			for(int i=2;i<=cnt;i++)
				if(s[i].maxx<a[minn_id[i-1]]) // 存在一个集合无法和前面的连边
					flag=0;
			if(!flag) puts("No");
			else
			{
				puts("Yes");
				// 先把集合自身连边
				for(int i=1;i<=cnt;i++)
				{
					for(int j=1;j<s[i].id.size();j++)
						cout<<a[s[i].id[0]]<<' '<<a[s[i].id[j]]<<'\n';
				}
				// 考虑集合之间的连边
				for(int i=2;i<=cnt;i++)
					cout<<a[minn_id[i-1]]<<' '<<s[i].maxx<<'\n';
			}
		}
	}
	return 0;
}

回复

3 条回复,欢迎继续交流。

正在加载回复...