[題解]火柴排隊
阿新 • • 發佈:2018-11-05
題目
解法
這道題實際上是一類問題:給你兩個序列 \(a(n) b(n)\),問最少花費幾步可以將\(a(n)\)變成\(b(n)\)。
如何做這種問題呢?
我們考慮這個步數要最小實際上是什麼,就是講優先順序一樣的放在兩個序列的相同位置,並且儘量讓每一個數移動的位置最少。
所以我們需要將\(a(n) 和 b(n)\)按照優先順序排序。
那排序後又怎麼做呢?
我們考慮構建一個新的陣列 \(c(n)\),其中 \( c[a[i],id] = b[i].id \)。
然後要讓 \(a(n)=b(n)\) 實際上就是要讓\(c[i]=i\) 也就是要讓b陣列中第i小的數和a陣列中第i小的數在同一個位置。
那麼這就轉化成了求解逆序對的數量了。
程式碼
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <cctype> #include <vector> #define INF 2139062143 #define MAX 0x7ffffffffffffff #define del(a,b) memset(a,b,sizeof(a)) usingView Codenamespace std; typedef long long ll; template<typename T> inline void read(T&x) { x=0;T k=1;char c=getchar(); while(!isdigit(c)){if(c=='-')k=-1;c=getchar();} while(isdigit(c)){x=x*10+c-'0';c=getchar();}x*=k; } const int maxn=1e5+15; const int mod=99999997; int n; int temp[maxn];struct node { int h,id; bool operator < (const node& x) const { return h==x.h?id<x.id:h<x.h; } }a[maxn],b[maxn]; #define lowbits(x) (x&(-x)) ll c[maxn]; inline void add(int pos,int k) { for(int i=pos;i<=n;i+=lowbits(i)) c[i]+=k; } inline ll query(int pos) { ll re=0; for(int i=pos;i;i-=lowbits(i)) re+=c[i]; return re; } int main() { read(n); for(int i=1;i<=n;i++) read(a[i].h),a[i].id=i; for(int i=1;i<=n;i++) read(b[i].h),b[i].id=i; sort(a+1,a+1+n);sort(b+1,b+1+n); for(int i=1;i<=n;i++) temp[b[i].id]=a[i].id; ll ans=0; for(int i=1;i<=n;i++) { ll k=query(temp[i]); ans+=i-1-k; add(temp[i],1ll); } printf("%lld\n",ans%mod); return 0; }