[NOIP2013 提高組] 火柴排隊
阿新 • • 發佈:2021-08-23
題目【逆序對應用】
思路
- 首先,什麼狀態是目標狀態
- 即(ai-bi)^2 最小的狀態=ai^2+bi^2-2aibi
- ai^2與bi^2不變, 主要要求sum(aibi)最大
- 可以證明,第二列的大小順序與第一列保持一致最大 即aibi差距最小最大
- 令x[sx[i]] = sx[i]
- x的逆序對即為需要交換的次數
程式碼
#include <bits/stdc++.h> using namespace std; const int N = 100010; const int mod = 1e8-3; int res=0; struct Node { int v,id; bool operator<(const Node& t) const { return v<t.v; } }a[N], b[N]; int x[N]; int tmp[N]; void msort(int l, int r) // 歸併排序 { if(l >= r) return; int mid = l+r>>1; msort(l,mid), msort(mid+1, r); //合併兩個有序陣列 int i=l, j=mid+1, k=0; while(i<=mid && j<=r) { if(x[i]<=x[j]) { tmp[k++] = x[i++]; }else { res = (res + mid-i+1)%mod; tmp[k++] = x[j++]; } } while(i<=mid) tmp[k++] = x[i++]; while(j<=r) tmp[k++] = x[j++]; for(int i=l; i<=r; ++i) x[i] = tmp[i-l];//還是[l,r]好 } int n; int main() { cin>>n; for(int i=1; i<=n; ++i) { scanf("%d", &a[i].v); a[i].id = i; } for(int i=1; i<=n; ++i) { scanf("%d", &b[i].v); b[i].id = i; } sort(a+1,a+n+1); sort(b+1,b+n+1); for(int i=1; i<=n; ++i) { x[a[i].id] = b[i].id; } msort(1,n); cout<<res; return 0; }