火柴排隊
阿新 • • 發佈:2020-10-26
目錄
思路
我們需要讓\(\sum_{i=1}^{n}(a_i-b_i)^2\)最小化,也就是等於\(0\),我們就需要讓\(a\)序列和\(b\)序列所有元素對應相同。
我們先離散化一下,然後就求最少幾個操作使得\(b\)序列轉換為\(a\)序列。
我們再建立一個陣列\(z\)。
假設我們現在有離散化後的序列 \(a = \{4, 3, 1, 2\},b = \{1, 3, 2, 4\}\)。
我們令\(z[a[i]]=b[i]\),相當於以\(a[i]\)為關鍵字對序列\(b[i]\)排序。
若序列\(a\)與序列\(b\)相等,那麼此時\(z[a[i]]\)應該等於\(a[i]\) 的,也就是\(z[i] = i\)。
如果我們要\(a\)序列與\(b\)序列相同,則我們需要將\(z\)陣列進行升序排列,那交換次數就是逆序對數。
我使用的樹狀陣列。
程式碼
#include <bits/stdc++.h> using namespace std; const long long MOD=99999997; int n; long long a[1000005],b[1000005],x[1000005],y[1000005],BIT[1000005],z[1000005]; bool cmp1(int x,int y) { return a[x]<a[y]; } bool cmp2(int x,int y) { return b[x]<b[y]; } int lowbit(int x) { return x & -x; } void update(int k,int x) { for(int i=k;i<=n;i+=lowbit(i)) BIT[i]+=x; return ; } long long ask(int x) { long long ans=0; for(int i=x;i;i-=lowbit(i)) ans+=BIT[i]; return ans; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); x[i]=y[i]=i; } for(int i=1;i<=n;i++) scanf("%d",&b[i]); sort(x+1,x+n+1,cmp1); sort(y+1,y+n+1,cmp2); for(int i=1;i<=n;i++) z[x[i]]=y[i]; long long ans=0; for(int i=1;i<=n;i++) { ans+=i-ask(z[i])-1; update(z[i],1); ans%=MOD; } printf("%lld",ans); return 0; }