专栏文章
题解:CF2031D Penchick and Desert Rabbit
CF2031D题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mir45ypv
- 此快照首次捕获于
- 2025/12/04 15:27 3 个月前
- 此快照最后确认于
- 2025/12/04 15:27 3 个月前
D
赛时的清奇想法。
首先发现能跳跃的两个位置是逆序对,因此考虑用并查集维护,并记录集合内最大值与最小值。
再考虑这样一种做法,先遍历一遍数组,目前遇到的最大值为 ,下标为 ,加入一个数 。
- 若 更新 和 。
- 若 那么就合并 和 。
以最后一组样例为例:


用 表示集合 中最大的 , 表示最小值。
然后考虑合并不同集合,从后往前,如果出现两个不同集合 且 。由前面的过程易知 ,如果 ,就说明这两个集合可以合并。
那有没有可能出现不是相邻的集合合并呢?答案是否定的,考虑 三个集合,,如果 与 不能合并,则 ,就会有 ,显然 与 不能合并。因此每个集合都只能和相邻的集合合并。
CPP那有没有可能出现不是相邻的集合合并呢?答案是否定的,考虑 三个集合,,如果 与 不能合并,则 ,就会有 ,显然 与 不能合并。因此每个集合都只能和相邻的集合合并。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
using namespace std;
typedef long long ll;
const int N=5e5+5;
int n;
int a[N],ans[N];
int fa[N],mi[N],mx[N];
int find(int x)
{
if(x==fa[x]) return x;
return fa[x]=find(fa[x]);
}
void merge(int x,int y)
{
x=fa[x],y=fa[y];
fa[y]=x;
mi[x]=min(mi[x],mi[y]);
mx[x]=max(mx[x],mx[y]);
}
void solve()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
fa[i]=i;
mi[i]=mx[i]=a[i];
}
int x=a[1],id=1;
for(int i=2;i<=n;i++)
{
if(a[i]<x) merge(id,i);
else x=a[i],id=i;
}
for(int i=n-1;i>=1;i--)
if(find(i)!=find(i+1)&&mi[find(i+1)]<mx[find(i)])
merge(i,i+1);
for(int i=1;i<=n;i++) cout<<mx[find(i)]<<' ';
cout<<'\n';
}
int main ()
{
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int T;
cin>>T;
while(T--) solve();
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...