P1966
[NOIP2013 提高组] 火柴排队
题目描述
涵涵有两盒火柴,每盒装有 \(n\) 根火柴,每根火柴都有一个高度。 现在将每盒中的火柴各自排成一列, 同一列火柴的高度互不相同, 两列火柴之间的距离定义为:$ \sum (a_i-b_i)^2$
其中 \(a_i\) 表示第一列火柴中第 \(i\) 个火柴的高度,\(b_i\) 表示第二列火柴中第 \(i\) 个火柴的高度。
每列火柴中相邻两根火柴的位置都可以交换,请你通过交换使得两列火柴之间的距离最小。请问得到这个最小的距离,最少需要交换多少次?如果这个数字太大,请输出这个最小交换次数对 \(10^8-3\) 取模的结果。
输入格式
共三行,第一行包含一个整数 \(n\),表示每盒中火柴的数目。
第二行有 \(n\) 个整数,每两个整数之间用一个空格隔开,表示第一列火柴的高度。
第三行有 \(n\) 个整数,每两个整数之间用一个空格隔开,表示第二列火柴的高度。
输出格式
一个整数,表示最少交换次数对 \(10^8-3\) 取模的结果。
样例 #1
样例输入 #1
4
2 3 1 4
3 2 1 4
样例输出 #1
1
样例 #2
样例输入 #2
4
1 3 4 2
1 7 2 4
样例输出 #2
2
提示
【输入输出样例说明一】
最小距离是$ 0$,最少需要交换 \(1\) 次,比如:交换第 $1 \(列的前\) 2$ 根火柴或者交换第 \(2\) 列的前 $2 $根火柴。
【输入输出样例说明二】
最小距离是 \(10\),最少需要交换 \(2\) 次,比如:交换第 \(1\) 列的中间 \(2\) 根火柴的位置,再交换第 \(2\) 列中后 \(2\) 根火柴的位置。
【数据范围】
对于 \(10\%\) 的数据, \(1 \leq n \leq 10\);
对于 \(30\%\) 的数据,\(1 \leq n \leq 100\);
对于 \(60\%\) 的数据,\(1 \leq n \leq 10^3\);
对于 \(100\%\) 的数据,\(1 \leq n \leq 10^5\),\(0 \leq\) 火柴高度 \(< 2^{31}\)。
超级好题!
首先可以直觉感觉出 肯定是最小的跟最小的 次小的跟次小的…(我发现了)
所以 首先离散化 (我也发现了)
可以感觉出答案跟逆序对有关 (我又发现了)
有个小结论:任意序列按题中交换方式回到1~n需要的次数就是逆序对数(我还是发现了)
最妙的一步(就差这步啊啊啊啊!):
构造一个映射 q[i]:a中的第i个在b中的位置!那么交换使得a=b
等价于将q排成1~n !!!!!!
所以答案就是q的逆序对数
随着难度的提高 练习的深入 要多掌握技巧方法 不要气馁 Forza!
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=100005;
const int mod=1e8-3;
int tr[maxn];
int n,a1[100005],b1[100005],c1[100005],a2[100005],b2[100005],c2[100005],p[maxn],q[maxn];
int lowbit(int x)
{
return x&(-x);
}
void add(int p,int k)
{
for(;p<=n;p+=lowbit(p))
tr[p]+=k;
}
int query(int p)
{
int sum=0;
for(;p;p-=lowbit(p))
sum+=tr[p];
return sum;
}
signed main()
{
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++)cin>>b1[i],c1[i]=b1[i];
for(int i=1;i<=n;i++)cin>>b2[i],c2[i]=b2[i];
sort(c1+1,c1+n+1);
for(int i=1;i<=n;i++)
{
int pos=lower_bound(c1+1,c1+n+1,b1[i])-c1;
a1[i]=pos;
}
sort(c2+1,c2+n+1);
for(int i=1;i<=n;i++)
{
int pos=lower_bound(c2+1,c2+n+1,b2[i])-c2;
a2[i]=pos;
}
for(int i=1;i<=n;i++)
p[a2[i]]=i;
for(int i=1;i<=n;i++)
q[i]=p[a1[i]];
// for(int i=1;i<=n;i++)cout<<q[i]<<" ";cout<<"\n";
int nxd=0;
for(int i=1;i<=n;i++)
{
add(q[i],1);
nxd+=i-query(q[i]);
nxd%=mod;
}
cout<<nxd<<"\n";
return 0;
}

浙公网安备 33010602011771号