luogu 1966 火柴排队

题目大意:

两列数,可以交换每列中相邻的两个数,算作一次交换

求最小的交换次数使两列数相对应的数之差的平方之和最小

思路:

首先可以明确当两列数的排序位置相对应时,为最佳答案

然后我们按照一中排序后在二中排序后出现的位置建一个数组

求一下逆序对

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<cstring>
 6 #include<cstdlib>
 7 #include<set>
 8 #include<map>
 9 #include<vector>
10 #include<stack>
11 #include<queue>
12 #define ll long long
13 #define inf 2147383611
14 #define MAXN 100100
15 #define MOD 99999997
16 using namespace std;
17 inline int read()
18 {
19     int x=0,f=1;
20     char ch;ch=getchar();
21     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
22     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
23     return x*f;
24 }
25 struct data
26 {
27     int pos,val;
28     bool operator < (const data &a) const
29     {
30         return val<a.val;
31     }
32 }a[MAXN],b[MAXN];
33 int g1[MAXN],g2[MAXN],k[MAXN],n,c[MAXN],cnt,ans;
34 int lowbit(int x) {return x&(-x);}
35 void add(int x,int val) {for(int i=x;i<=MAXN;i+=lowbit(i)) c[i]+=val;}
36 int sum(int x) {int res=0;for(int i=x;i;i-=lowbit(i)) res+=c[i];return res;}
37 int main()
38 {
39     n=read();
40     for(int i=1;i<=n;i++) a[i].val=read(),a[i].pos=i;
41     sort(a+1,a+n+1);
42     for(int i=1;i<=n;i++) b[i].val=read(),b[i].pos=i;
43     sort(b+1,b+n+1);
44     for(int i=1;i<=n;i++) k[a[i].pos]=b[i].pos;
45     for(int i=1;i<=n;i++)
46     {
47         ans=((ans+i-1)%MOD-sum(k[i]-1)%MOD)%MOD;
48         add(k[i],1);
49     }
50     printf("%d",ans);
51 }
View Code
原文地址:https://www.cnblogs.com/yyc-jack-0920/p/7754704.html