P6687 论如何玩转 Excel 表格(逆序对)

当时写的时候真是一点思路没有

菜是原罪,白学一年

假 设 现 在 已 经 知 道 一 定 有 解 假设现在已经知道一定有解

那 把 每 一 列 看 成 一 个 整 体 , 这 个 整 体 是 不 会 拆 开 的 那把每一列看成一个整体,这个整体是不会拆开的 ,

在 旋 转 的 过 程 中 只 会 上 下 颠 倒 , 这 无 所 谓 ( 因 为 一 定 有 解 ) 在旋转的过程中只会上下颠倒,这无所谓(因为一定有解) ,()

同 时 旋 转 可 以 看 成 相 邻 两 列 交 换 位 置 同时旋转可以看成相邻两列交换位置

这 就 是 冒 泡 排 序 啊 ! ! 问 交 换 几 次 变 成 目 标 序 列 这就是冒泡排序啊!!问交换几次变成目标序列 !!

把 目 标 序 列 看 成 把目标序列看成 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;
	}
}
©️2020 CSDN 皮肤主题: 1024 设计师:上身试试 返回首页