[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 个测试点。
浙公网安备 33010602011771号