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";
	}
}
相关推荐
nnsix1 小时前
JIT(即时编译)、 AOT(预先编译)、虚拟机CLR 笔记
笔记
筠筠喵呜喵2 小时前
Linux软件开发性能优化
linux·c++·性能优化
NULL指向我2 小时前
Simplis仿真笔记1:Simplis_V8.4_x64安装过程
笔记
Bruce_kaizy2 小时前
c++ linux环境编程——文件io介绍以及open 、write 、read 三剑客深度详解
linux·服务器·c++·ubuntu·操作系统·文件io
ouliten3 小时前
[Triton笔记6]层标准化
笔记
PAK向日葵4 小时前
我用 C++ 写了一个轻量级 Python 虚拟机,刚刚开源
c++·python·开源
玖釉-4 小时前
下一个排列:从字典序到原地算法的完整推导
数据结构·c++·windows·算法
IronMurphy4 小时前
【算法五十】62. 不同路径
算法