当时写的时候真是一点思路没有
菜是原罪,白学一年
假 设 现 在 已 经 知 道 一 定 有 解 假设现在已经知道一定有解 假设现在已经知道一定有解
那 把 每 一 列 看 成 一 个 整 体 , 这 个 整 体 是 不 会 拆 开 的 那把每一列看成一个整体,这个整体是不会拆开的 那把每一列看成一个整体,这个整体是不会拆开的
在 旋 转 的 过 程 中 只 会 上 下 颠 倒 , 这 无 所 谓 ( 因 为 一 定 有 解 ) 在旋转的过程中只会上下颠倒,这无所谓(因为一定有解) 在旋转的过程中只会上下颠倒,这无所谓(因为一定有解)
同 时 旋 转 可 以 看 成 相 邻 两 列 交 换 位 置 同时旋转可以看成相邻两列交换位置 同时旋转可以看成相邻两列交换位置
这 就 是 冒 泡 排 序 啊 ! ! 问 交 换 几 次 变 成 目 标 序 列 这就是冒泡排序啊!!问交换几次变成目标序列 这就是冒泡排序啊!!问交换几次变成目标序列
把 目 标 序 列 看 成 把目标序列看成 把目标序列看成 1 2 3 4 5 …
映 射 到 自 己 , 求 逆 序 对 了 映射到自己,求逆序对了 映射到自己,求逆序对了~~
无解的情况看代码吧
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define f first
#define s second
const int maxn=2e6+10;
int n,a[3][maxn],b[3][maxn],flag=1,id[maxn],temp[maxn],ans;
typedef pair<int,int>p;
p vis[maxn];
inline int slow_read()
{
long long s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
void merge_sort(int l,int mid,int r)
{
int p1=l,p2=mid+1,top=l-1;
while( p1<=mid&&p2<=r )
{
if( id[p1]>id[p2] ) temp[++top]=id[p2++],ans+=(mid-p1+1);
else temp[++top]=id[p1++];
}
while( p1<=mid ) temp[++top]=id[p1++];
while( p2<=r ) temp[++top]=id[p2++];
for(int i=l;i<=r;i++) id[i]=temp[i];
return;
}
void merge(int l,int r)
{
if( l>=r ) return;
int mid=l+r>>1;
merge(l,mid);
merge(mid+1,r);
merge_sort(l,mid,r);
}
signed main()
{
n=slow_read();
for(int i=1;i<=2;i++)
for(int j=1;j<=n;j++)
a[i][j]=slow_read();
for(int i=1;i<=2;i++)
for(int j=1;j<=n;j++)
{
b[i][j]=slow_read();
vis[ b[i][j] ]=p(i,j);
}
for(int i=1;i<=n;i++)//遍历每一列
{
int q=a[1][i],w=a[2][i];
if( vis[q].s!=vis[w].s ) flag=0;//不在一列,不符合
int cha=abs(vis[q].s-i);
if( cha%2==1&&vis[q].f==1 ) flag=0;
if( cha%2==0&&vis[q].f==2 ) flag=0;
id[i]=vis[q].s;
}
if( flag==0 ) cout << "dldsgay!!1";
else
{
merge(1,n);
cout << ans;
}
}