[AGC001F] Wide Swap 题解

题目让满足 \(|p_i-p_j| \le 1 , j - i \geq k-1\)。(下文的\(a_i\)\(p_i\)\(p_i\)\(a_i\)的逆置换。)

给出样例:

输入输出样例 #1

输入 #1

4 2
4 2 3 1

输出 #1

2
1
4
3

输入输出样例 #2

输入 #2

5 1
5 4 3 2 1

输出 #2

1
2
3
4
5

输入输出样例 #3

输入 #3

8 3
4 5 7 8 3 1 2 6

输出 #3

1
2
6
7
5
3
4
8

我们观察以上样例,随便玩玩样例一我们会发现,只要每一次我们都是用前头的小的换后头的大的,一定可以得出最优解,然后我们就可以想到每个点跑一次看能不能和后面的点换,可是我们发现样例2过不了,我们考虑让他跑5次。

代码:

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=5e5+10;
int n,m,a[maxn],p[maxn];
signed main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		p[a[i]]=i;
	}
	for(int ci=1;ci<=5;ci++){
		for(int i=1;i<=n;i++){
			while(p[a[i]-1]-i>=m){
				p[a[i]]=p[a[i]-1];
				swap(a[i],a[p[a[i]-1]]);
				p[a[i]]=i;
			}
		}
	}
	for(int i=1;i<=n;i++){
		cout<<a[i]<<'\n';
	}
	return 0;
}

能通过 42/94 个测试点。

然后我们可以想到卡时,只要不超时就跑即可。

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=5e5+10;
int n,m,a[maxn],p[maxn];
double qi;
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	qi=clock();
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		p[a[i]]=i;
	}
	while((double)(clock()-qi)/CLOCKS_PER_SEC<1.9){
		for(int i=1;i<=n;i++){
			while(p[a[i]-1]-i>=m){
				p[a[i]]=p[a[i]-1];
				swap(a[i],a[p[a[i]-1]]);
				p[a[i]]=i;
			}
		}
	}
	for(int i=1;i<=n;i++){
		cout<<a[i]<<'\n';
	}
	return 0;
}

能通过 68/94 个测试点。

然后我们容易发现我们可以给他一个逆置换看着很舒服。(相当于把我的\(a_i,p_i\)互换)

条件变为了\(p_i-p_{i-1} \le m\)即可交换,问最大的排列是多少。

然后使用冒泡排序:

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=5e5+10;
int n,m,a[maxn],p[maxn],flag;
double qi;
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	qi=clock();
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		p[a[i]]=i;
	}
	for(int i=1;i<=n;i++){
		flag=0;
		for(int j=1;j<=n-i;j++){
			if(p[j]-p[j+1]>=m){
				swap(p[j],p[j+1]);
				flag=1;
			}
		}
		if(!flag){
			break;
		}
	}
	for(int i=1;i<=n;i++){
		a[p[i]]=i;
	}
	for(int i=1;i<=n;i++){
		cout<<a[i]<<'\n';
	}
	return 0;
}

可以通过 38/94 个测试点。

剩余的全部是TLE,尝试改成归并排序。

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=5e5+10;
int n,m,a[maxn],p[maxn],flag,lin,b[maxn];
int mn[maxn],L,R,wei;
void bing(int l,int r){
	if(l==r){
		return;
	}
	int mid=(l+r)/2;
	bing(l,mid);
	bing(mid+1,r);
	lin=1e9;
	for(int i=mid;i>=l;i--){
		lin=min(lin,p[i]);
		mn[i]=lin;
	}
	L=l;
	R=mid+1;
	wei=l;
	while(L<=mid&&R<=r){
		if(mn[L]>=p[R]+m){
			b[wei]=p[R];
			R++;
			wei++;
		}
		else{
			b[wei]=p[L];
			L++;
			wei++;
		}
	}
	while(L<=mid){
		b[wei]=p[L];
		L++;
		wei++;
	}
	while(R<=r){
		b[wei]=p[R];
		R++;
		wei++;
	}
	for(int i=l;i<=r;i++){
		p[i]=b[i];
	}
	return;
}
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		p[a[i]]=i;
	}
	bing(1,n);
	for(int i=1;i<=n;i++){
		a[p[i]]=i;
	}
	for(int i=1;i<=n;i++){
		cout<<a[i]<<'\n';
	}
	return 0;
}

可以通过 94/94 个测试点。

posted @ 2025-04-30 10:21  特别之处  阅读(19)  评论(0)    收藏  举报