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 }