社区讨论
代码求调(有思路)
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 条回复,欢迎继续交流。
正在加载回复...