CF2217E Definitely Larger 题解

题面链接

思路

作者一开始把题读漏了,没看着 p ,   q p,\,q p,q 都是 1 ∼ n 1\sim n 1∼n 排列,还在想着要处理 p p p 值相等的情况,于是直接卡死了。(应该没有人像我这样吧)

我们用 a i a_i ai 表示可能支配 i i i 的位置个数,初始值就是有几个 j > i j>i j>i 满足 p j > p i p_j>p_i pj>pi。从 1 1 1 开始从小往大往 q q q 里面填值。 在填 1 1 1 的时候, q q q 里面还没有值,未来也不可能有比 1 1 1 小的值,如果在 q i q_i qi 处填 1 1 1,所有 j > i ,   p j > p i j>i,\,p_j>p_i j>i,pj>pi 的都一定支配 i i i,所以必须满足 d i = a i d_i=a_i di=ai。我们要做的就是找到一个位置 d i = a i d_i=a_i di=ai,然后把 1 1 1 扔进去。

那如果有很多位置都相等呢?我们先来看看把 1 1 1 放进去之后有什么影响。由于这个位置一定比未来填写的位置要更小,不能再支配别人,所以它必须从 j < i ,   p j < p i j<i,\,p_j<p_i j<i,pj<pi 的 j j j 的可能支配位置中移除,这些 j j j 的 a j a_j aj 需要减一。对于其他位置就没有影响了。进行完这个操作之后,就可以填入 2 2 2,此时 2 2 2 是所有有影响的 q q q 值中最小的( q i = 1 q_i=1 qi=1 的位置对其他位置的影响已经通过把 a j a_j aj 减一消除了),就和上面填 1 1 1 的做法一样。接下来也能用一样的方法填入 3 ,   4 ,   5 , ... 3,\,4,\,5,\dots 3,4,5,...。

现在我们再考虑多个位置满足条件的情况。此时必须选择最前面的位置,如果选了不是最前面的位置 i i i,会把一些 j < i j<i j<i 的 a j a_j aj 减一,然而在 i i i 之前的一些 a j a_j aj 是和 d j d_j dj 相等的,那么减完之后 a j < d j a_j<d_j aj<dj。在整个过程中 a a a 单调不增,这样 a j a_j aj 就再也不可能等于 d j d_j dj 了,也不可能再有数填入位置 j j j,就无解了。

什么时候无解呢?上面提到过,如果出现一个 a i < d i a_i<d_i ai<di,就完蛋了。还有,如果找不到一个 a i = d i a_i=d_i ai=di,就是 a a a 都太大了,也无解。

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ll long long
int t,n,p[5005],d[5005],a[5005],q[5005];
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cin>>t;
	while(t--){
		cin>>n;
		for(int i=1;i<=n;i++) a[i]=q[i]=0;
		for(int i=1;i<=n;i++){
			cin>>p[i];
			for(int j=1;j<i;j++)
				if(p[j]<p[i]) a[j]++;
		}
		for(int i=1;i<=n;i++) cin>>d[i];
		bool succ=1;
		for(int i=1;i<=n;i++){
			int rec=0;
			for(int j=1;j<=n;j++){
				if(q[j]) continue;
				if(a[j]==d[j]){
					q[j]=i;
					rec=j;
					break;
				}
				if(a[j]<d[j]){
					succ=0;
					break;
				}
			}
			if(rec==0) succ=0;
			if(!succ) break;
			for(int j=1;j<rec;j++)
				if(p[j]<p[rec]) a[j]--;
		}
		if(succ){
			for(int i=1;i<=n;i++) cout<<q[i]<<' ';
			cout<<endl;
		}
		else cout<<"-1\n";
	}
}
相关推荐
JieE21214 小时前
LeetCode 56. 合并区间|超清晰 JS 图解思路,面试高频区间题
javascript·算法·面试
Jack201 天前
HarmonyOS开发中错误处理策略:网络异常统一处理
算法
小小杨树1 天前
读懂色彩:拍照调色不再难
算法·计算机视觉·配色
JieE2122 天前
LeetCode 226. 翻转二叉树|JS 递归超详细拆解,二叉树入门经典题
javascript·算法
JieE2122 天前
LeetCode 104. 二叉树的最大深度|递归思路超详细拆解
javascript·算法
vivo互联网技术2 天前
CVPR 2026 | 全新强化学习框架 BeautyGRPO:重塑真实人像
算法·大模型·cvpr·影像
Darling噜啦啦2 天前
列表转树算法深度解析:从 Map 到 Reduce 的两种实现,面试高频考点
数据结构·算法·面试
clint4562 天前
C++进阶(1)——前景提要
c++
用户497863050732 天前
(一)小红的数组操作
算法·编程语言