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";
	}
}
相关推荐
凯瑟琳.奥古斯特31 分钟前
力扣1015C++解法技巧
c++·算法·leetcode·链表·职场和发展
seowmt40 分钟前
GEO效果该什么时候看数据:从立项到复盘的时间线复盘
算法·ip·seo·geo·faq
悠仁さん40 分钟前
【算法C++】双指针(一)
数据结构·c++·算法
jimy11 小时前
lvalue、xvalue、prvalue(二):引用是哪一类?
开发语言·c++·1024程序员节
小豆庄1 小时前
本地视频脱敏的追踪系统踩坑——车牌过滤、转场误判与ID冲突排查
人工智能·算法·目标检测·音视频·视频·敏捷流程·纹理贴图
忆挽篱笙歌1 小时前
进程替换函数与shenll命令行解释器
前端·javascript·算法
YukiRinLL1 小时前
字符串存储与 BF、KMP 匹配算法
数据结构·算法
小超人诞生日记1 小时前
Linux:环境变量 & 进程虚拟地址空间
linux·算法
杜 硕1 小时前
从零开始的C++生活——第三讲
开发语言·c++·生活
小白起 v1 小时前
【算法学习 · 01】深入理解大 O 表示法:从「能跑就行」到「专业评估」算法性能
算法