桂林 Problem D. Assumption is All You Need 题解(构造+思维)
题目思路
暂时无题目链接
问了一下其他队过的思路,大概是这样
别人的口胡
从小到大先把1移到它要去的地方然后再移2一直到n,但是不是直接移动
比如现在1的位置是5最终要到位置1,你就先区间查询1-4位置的最小值,然后把1移到查询的位置
然后这个区间的最小值移动到了5这个位置然后继续查询位置1到当前位置的最小值然后再往前移动
这样次小的可以跟最小的再移动5 4 2 3 1先把1移动到3这个位置5 4 1 3 2你看看除了1往前走了
其他位置的值还是可以和原本一样移动2选择还可以更多处理完后你还可以将大的值再移动到最后
你这样保证了移动前后其他位置的选择不会减少你就看成处理完1 就把1这个位置去掉
因为1不能给贡献了剩下的点选择和之前一样多
代码
代码还没测验过,不保证正确性
#include<bits/stdc++.h>
#define fi first
#define se second
#define debug cout<<"I AM HERE"<<endl;
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn=2e5+5,inf=0x3f3f3f3f,mod=29;
const double eps=1e-6;
const ll INF=0x3f3f3f3f3f3f3f3f;
int n;
int a[maxn],b[maxn];
int posa[maxn],posb[maxn];
void sw(int i,int j){
int tmpi=a[i];
int tmpj=a[j];
a[i]=tmpj;
a[j]=tmpi;
posa[a[i]]=i;
posa[a[j]]=j;
}
signed main(){
int _;scanf("%d",&_);
while(_--){
vector<pair<int,int> > ans;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
posa[a[i]]=i;
}
for(int i=1;i<=n;i++){
scanf("%d",&b[i]);
posb[b[i]]=i;
}
bool flag=1;
for(int i=1;i<=n;i++){
if(posa[i]==posb[i]) continue;
if(posa[i]<posb[i]){
flag=0;
break;
}
int nowl=posb[i];
int nowr=posa[i];
for(int j=i+1;j<=n;j++){
if(posa[j]<=nowr&&posa[j]>=nowl){
ans.push_back({posa[j],nowr});
int tmp=posa[j];
sw(posa[j],nowr);
nowr=tmp;
}
}
}
for(int i=1;i<=n;i++){
if(a[i]!=b[i]){
flag=0;
}
}
if(!flag){
printf("-1\n");
}else{
printf("%d\n",ans.size());
for(auto x:ans){
printf("%d %d\n",x.fi,x.se);
}
}
}
return 0;
}
不摆烂了,写题