LOJ2609. NOIP2013 火柴排队 【树状数组】

LOJ2609. NOIP2013 火柴排队


LINK


题目大意:
给你两个数列,定义权值∑i=1(ai−bi)^2
问最少的操作次数,最小化权值


首先需要发现几个性质

  1. 最小权值满足任意i,j不存在ai>aj,bi<bj
  2. 只需要改变一个序列的顺序就足够了
  3. 把一个序列排序成有序的最少操作次数是逆序对个数

然后就可以随便做了


 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 100010
 4 #define Mod 99999997
 5 struct Node{int val,id;}a[N],b[N];
 6 int n,match[N];
 7 bool cmp(Node a,Node b){return a.val<b.val;}
 8 int t[N];
 9 int add(int a,int b){return (a+b)%Mod;}
10 void add(int x){while(x<=n)t[x]++,x+=x&(-x);}
11 int query(int x){int res=0;while(x)res=add(res,t[x]),x-=x&(-x);return res;}
12 int main(){
13     scanf("%d",&n);
14     for(int i=1;i<=n;i++)a[i].id=b[i].id=i;
15     for(int i=1;i<=n;i++)scanf("%d",&a[i].val);
16     for(int i=1;i<=n;i++)scanf("%d",&b[i].val);
17     sort(a+1,a+n+1,cmp);
18     sort(b+1,b+n+1,cmp);
19     for(int i=1;i<=n;i++)match[a[i].id]=b[i].id;
20     int ans=0;
21     for(int i=n;i>=1;i--){
22         ans=add(ans,query(match[i]));
23         add(match[i]);
24     }
25     printf("%d",ans);
26     return 0;
27 }
原文地址:https://www.cnblogs.com/dream-maker-yk/p/9676265.html