【洛谷P1966】火柴排队
火柴排队
∑(ai−bi)^2=∑ai^2-2*∑ai*bi+∑bi^2
显然∑ai^2+∑bi^2是不变的,我们要让
2*∑ai*bi最大,才能使原式最小
然后我们一眼就可以看出来,
当第i大的ai与第i大的bi一一对应时,∑ai*bi最大
反正我不会证
知道了对应关系后,于是就成了求逆序对的个数了
可以用归并排序或树状数组
1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 using namespace std; 6 #define N 1000010 7 #define mod 99999997 8 int n,a[N],ans; 9 struct HC{ 10 int pos,val; 11 } A[N],B[N]; 12 inline int read(){ 13 int x=0; char c=getchar(); 14 while(c<'0'||c>'9') c=getchar(); 15 while('0'<=c&&c<='9') { x=(x<<3)+(x<<1)+c-'0'; c=getchar(); } 16 return x; 17 } 18 inline bool cmp(HC a,HC b){ 19 return a.val<b.val; 20 } 21 int f[N]; 22 void msort(int l,int r){ 23 if(l>=r) return; 24 int mid=(l+r)>>1; 25 msort(l,mid); msort(mid+1,r); 26 int i=l,j=mid+1,k=1; 27 while(i<=mid&&j<=r){ 28 if(a[i]<=a[j]){ 29 f[k]=a[i]; 30 i++; k++; 31 } 32 else{ 33 f[k]=a[j]; 34 ans+=mid-i+1; 35 if(ans>mod) ans-=mod; 36 j++; k++; 37 } 38 } 39 while(i<=mid){ f[k]=a[i]; i++; k++; } 40 while(j<=r) { f[k]=a[j]; j++; k++; } 41 for(int i=1;i<=r-l+1;i++) 42 a[l+i-1]=f[i]; 43 } 44 int main() 45 { 46 scanf("%d",&n); 47 for(int i=1;i<=n;i++){ 48 A[i].val=read(); 49 A[i].pos=i; 50 } 51 for(int i=1;i<=n;i++){ 52 B[i].val=read(); 53 B[i].pos=i; 54 } 55 sort(A+1,A+1+n,cmp); 56 sort(B+1,B+1+n,cmp); 57 for(int i=1;i<=n;i++) 58 a[B[i].pos]=A[i].pos; 59 msort(1,n); 60 printf("%d\n",ans%mod); 61 return 0; 62 }