洛谷 P1966 火柴排队 题解
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷 P1966 火柴排队 题解相关的知识,希望对你有一定的参考价值。
此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置。
题目链接:https://www.luogu.org/problem/show?pid=1966
题目描述
涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度。 现在将每盒中的火柴各自排成一列, 同一列火柴的高度互不相同, 两列火柴之间的距离定义为: ∑(ai-bi)^2
其中 ai 表示第一列火柴中第 i 个火柴的高度,bi 表示第二列火柴中第 i 个火柴的高度。
每列火柴中相邻两根火柴的位置都可以交换,请你通过交换使得两列火柴之间的距离最小。请问得到这个最小的距离,最少需要交换多少次?如果这个数字太大,请输出这个最小交换次数对 99,999,997 取模的结果。
输入输出格式
输入格式:输入文件为 match.in。
共三行,第一行包含一个整数 n,表示每盒中火柴的数目。
第二行有 n 个整数,每两个整数之间用一个空格隔开,表示第一列火柴的高度。
第三行有 n 个整数,每两个整数之间用一个空格隔开,表示第二列火柴的高度。
输出格式:输出文件为 match.out。
输出共一行,包含一个整数,表示最少交换次数对 99,999,997 取模的结果。
输入输出样例
4 2 3 1 4 3 2 1 4
1
4 1 3 4 2 1 7 2 4
2
说明
【输入输出样例说明1】
最小距离是 0,最少需要交换 1 次,比如:交换第 1 列的前 2 根火柴或者交换第 2 列的前 2 根火柴。
【输入输出样例说明2】
最小距离是 10,最少需要交换 2 次,比如:交换第 1 列的中间 2 根火柴的位置,再交换第 2 列中后 2 根火柴的位置。
【数据范围】
对于 10%的数据, 1 ≤ n ≤ 10;
对于 30%的数据,1 ≤ n ≤ 100;
对于 60%的数据,1 ≤ n ≤ 1,000;
对于 100%的数据,1 ≤ n ≤ 100,000,0 ≤火柴高度≤ maxlongint
分析:
要使对应序号的数字差最小,应该让a中最大对应b中最大,a中次大对应b中次大……
(然后忘记了老师是怎么讲的)
总之就是对a进行一下离散化,用rank数组对应a,b的编号,然后求逆序对即为答案。
AC代码:
1 #include<cstdio> 2 #include<algorithm> 3 #include<cmath> 4 #include<cstring> 5 6 const int MOD = 99999997; 7 const int MAXN = 100005; 8 9 inline void read(int &x) 10 { 11 char ch = getchar(),c = ch;x = 0; 12 while(ch < ‘0‘ || ch > ‘9‘) c = ch,ch = getchar(); 13 while(ch <= ‘9‘ && ch >= ‘0‘) x = (x<<1)+(x<<3)+ch-‘0‘,ch = getchar(); 14 if(c == ‘-‘) x = -x; 15 } 16 17 int n,rank[MAXN]; 18 long long ans; 19 20 struct NUM 21 { 22 int ord,v; 23 }a[MAXN],b[MAXN]; 24 25 int cmp(NUM a,NUM b) 26 {return a.v < b.v;} 27 28 inline int lowbit(int x) 29 {return x&(-x);} 30 31 inline void update(int x,int num) 32 { 33 while(x <= n) 34 { 35 c[x] += num; 36 x += lowbit(x); 37 } 38 } 39 40 inline int sum(int x) 41 { 42 int sum = 0; 43 while(x > 0) 44 { 45 sum += c[x]; 46 x -= lowbit(x); 47 } 48 return sum; 49 } 50 int main() 51 { 52 read(n); 53 for(register int i = 1;i <= n;++ i) 54 read(a[i].v),a[i].ord = i; 55 for(register int i = 1;i <= n;++ i) 56 read(b[i].v),b[i].ord = i; 57 std::sort(a+1,a+1+n,cmp); 58 std::sort(b+1,b+1+n,cmp); 59 for(register int i = 1;i <= n;++ i) 60 rank[a[i].ord] = b[i].ord; 61 for(register int i = 1;i <= n;++ i) 62 { 63 update(rank[i],1); 64 ans = (ans + i - sum(rank[i]))%MOD; 65 } 66 printf("%lld\n",ans); 67 return 0; 68 }
以上是关于洛谷 P1966 火柴排队 题解的主要内容,如果未能解决你的问题,请参考以下文章