不懂LIS可以先访问:传送门
问题 C: Swap
时间限制: 10 Sec 内存限制: 128 MB
题目描述
如果你需要移动一样东西,显然接触或者使用磁场电场之类的可以解决。但是有没有办法进行超越距离的随心所欲的移动?
对于物体或者文字进行超距离移动一直是人类的梦想,有一天这个难题终于被我们的大牛解决了!他现在需要的就是整理数列。数列就是所谓的写在纸上或者在电脑品目上的数列…
整理数列需要一个叫做swap的操作,swap操作就是指大牛通过超距离的控制把数列中的某一位直接插入某两位的中间或者数列的开始或者终止的操作。这个操作的关键在于超距离控制,显然这种事情不能干太多次,不但降RP,而且很耗体力。你的任务就是从初始状态到目标状态所需要做swap的最少次数。
输入
三行,第一行一个整数 n(n<600000)
第二行,n 个整数(1-n),表示初始数列。
第三行,n 个整数(1-n),表示目标数列。
保证整数不重复。
输出
一行 表示最少swap次数。
样例输入 Copy
10
1 2 3 4 5 6 7 8 9 10
10 9 8 7 6 5 4 3 2 1
样例输出 Copy
9
题意:
给定两个1~n的全排列a,b,问最少要经过多少次swap操作能够使得a变为b。其中swap操作表示可以把任意一个数插到任意位置。
思路:
很容易想到的是,对于a和b的LCS,我们可以直接保留,然后把剩下的插到对应位置即可,这样答案就是n-LCS。求LCS的复杂度是O(n^2),对于此题显然行不通。
优化就是将LCS转化为LIS问题,原理
代码:
#pragma GCC optimize(3) //#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline") //#include<bits/stdc++.h> #include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> #include<cassert> #include<bitset> ///#include<unordered_map> using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<ll,ll>PLL; typedef pair<int,int>PII; typedef pair<double,double>PDD; #define I_int ll #define modl 19260817*19890604-19491001 #define x first #define y second inline ll read() { ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } char F[200]; inline void out(I_int x) { if (x == 0) return (void) (putchar('0')); I_int tmp = x > 0 ? x : -x; if (x < 0) putchar('-'); int cnt = 0; while (tmp > 0) { F[cnt++] = tmp % 10 + '0'; tmp /= 10; } while (cnt > 0) putchar(F[--cnt]); //cout<<" "; } ll ksm(ll a,ll b,ll p){ll res=1;while(b){if(b&1)res=res*a%p;a=a*a%p;b>>=1;}return res;} const int inf=0x3f3f3f3f,mod=1e9+7; const ll INF = 0x3f3f3f3f3f3f3f3f; const int maxn=6e5+100,maxm=3e6+7; ll a[maxn],b[maxn],dp[maxn]; int cnt=0; ll q[maxn]; int Find(int x){ int l=1,r=cnt; while(l<r){ int mid=(l+r)>>1; if(q[mid]>=x) r=mid; else l=mid+1; } return l; } int main(){ int n=read(); for(int i=1;i<=n;i++){ int tmp=read(); a[tmp]=i; } for(int i=1;i<=n;i++){ int tmp=read(); b[i]=a[tmp]; } q[++cnt]=b[1]; for(int i=2;i<=n;i++) if(b[i]>q[cnt]) q[++cnt]=b[i]; else{ int tmp=Find(b[i]); q[tmp]=b[i]; } out(n-cnt); return 0; }