【noip 2013】火柴排队
2017-08-03 16:06
274 查看
离noip2017还有99天了,开个博客记录一下,不要让自己颓废
题目描述
涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度。 现在将每盒中的火柴各自排成一列, 同一列火柴的高度互不相同, 两列火柴之间的距离定义为: ∑(ai-bi)^2 其中 ai 表示第一列火柴中第 i 个火柴的高度,bi表示第二列火柴中第 i 个火柴的高度。
每列火柴中相邻两根火柴的位置都可以交换,请你通过交换使得两列火柴之间的距离最小。请问得到这个最小的距离,最少需要交换多少次?如果这个数字太大,请输出这个最小交换次数对99,999,997 取模的结果。
输入格式:
共三行,第一行包含一个整数 n,表示每盒中火柴的数目。 第二行有 n 个整数,每两个整数之间用一个空格隔开,表示第一列火柴的高度。 第三行有 n 个整数,每两个整数之间用一个空格隔开,表示第二列火柴的高度。
输出格式:
输出共一行,包含一个整数,表示最少交换次数对 99,999,997 取模的结果。
数据范围:
对于 100%的数据,1 ≤ n ≤ 100,000,0 ≤火柴高度≤ maxlongint
这道题洛谷评为提高+/省选-,我觉得还是略水(虽然我只是一个学了几个月编程的蒟蒻),比起别的题目来说这道题还是比较好想的。
首先,什么状态下火柴距离最小?我第一反应就是如果a列第i高的火柴和b列第i高的火柴一一对应,这时距离应该是最小的。因为我很菜,所以一时半会没想出来证明方法。但按照“两数和相等差越小积越大”这种感觉应该是对的(领会精神….)。
然后,问题就来到了如何用最少的交换次数达到高度排名的一一对应?显然,如果以第一列火柴为标准,那么我们可以只交换第二列火柴达到目的。有一点冒泡排序的味道,而冒泡排序可以…对!求逆序对!如果对第二列火柴进行编号,问题就转化为求第二列火柴高度排名的逆序对的个数,用归并排序就可以解决因为我不会用树状数组求.
问题是,怎样重新编号?思考之后,我发现问题的本质就是要找b列火柴中的哪一根与a列火柴的哪一根在各自队伍中的排名相同,那么就给这两根火柴相同的编号i,i是该火柴在a列火柴中的位置。现在问题就变得明了了,要求排名相同的火柴,我们只需要排序,并开一个结构体记录火柴本来的位置,就解决了问题。
代码如下:
题目描述
涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度。 现在将每盒中的火柴各自排成一列, 同一列火柴的高度互不相同, 两列火柴之间的距离定义为: ∑(ai-bi)^2 其中 ai 表示第一列火柴中第 i 个火柴的高度,bi表示第二列火柴中第 i 个火柴的高度。
每列火柴中相邻两根火柴的位置都可以交换,请你通过交换使得两列火柴之间的距离最小。请问得到这个最小的距离,最少需要交换多少次?如果这个数字太大,请输出这个最小交换次数对99,999,997 取模的结果。
输入格式:
共三行,第一行包含一个整数 n,表示每盒中火柴的数目。 第二行有 n 个整数,每两个整数之间用一个空格隔开,表示第一列火柴的高度。 第三行有 n 个整数,每两个整数之间用一个空格隔开,表示第二列火柴的高度。
输出格式:
输出共一行,包含一个整数,表示最少交换次数对 99,999,997 取模的结果。
数据范围:
对于 100%的数据,1 ≤ n ≤ 100,000,0 ≤火柴高度≤ maxlongint
这道题洛谷评为提高+/省选-,我觉得还是略水(虽然我只是一个学了几个月编程的蒟蒻),比起别的题目来说这道题还是比较好想的。
首先,什么状态下火柴距离最小?我第一反应就是如果a列第i高的火柴和b列第i高的火柴一一对应,这时距离应该是最小的。因为我很菜,所以一时半会没想出来证明方法。但按照“两数和相等差越小积越大”这种感觉应该是对的(领会精神….)。
然后,问题就来到了如何用最少的交换次数达到高度排名的一一对应?显然,如果以第一列火柴为标准,那么我们可以只交换第二列火柴达到目的。有一点冒泡排序的味道,而冒泡排序可以…对!求逆序对!如果对第二列火柴进行编号,问题就转化为求第二列火柴高度排名的逆序对的个数,用归并排序就可以解决因为我不会用树状数组求.
问题是,怎样重新编号?思考之后,我发现问题的本质就是要找b列火柴中的哪一根与a列火柴的哪一根在各自队伍中的排名相同,那么就给这两根火柴相同的编号i,i是该火柴在a列火柴中的位置。现在问题就变得明了了,要求排名相同的火柴,我们只需要排序,并开一个结构体记录火柴本来的位置,就解决了问题。
代码如下:
#include<cstdio> #include<iostream> #include<algorithm> using namespace std; struct node{ int ind; long long h; }a[100001],b[100001]; int ans=0; int c[100001]; int tmp[100001]; const int mod=99999997; bool cmp(node a,node b) { return a.h<b.h; } long long read() { long long x=0; char c=getchar(); while(c<'0'||c>'9') c=getchar(); while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); return x; } void msort(int l,int r) { if(l==r) return ; int mid=(l+r)/2; msort(l,mid); msort(mid+1,r); int i=l,j=mid+1,k=l; while(i<=mid&&j<=r) { if(c[i]<=c[j]) tmp[k++]=c[i++]; else { tmp[k++]=c[j++]; ans+=mid-i+1; ans%=mod; } } while(i<=mid) tmp[k++]=c[i++]; while(j<=r) tmp[k++]=c[j++]; for(int i=l;i<=r;i++) c[i]=tmp[i]; } int main() { int n; n=read(); for(int i=1;i<=n;i++) { a[i].h=read(); a[i].ind=i; } for(int i=1;i<=n;i++) { b[i].h=read(); b[i].ind=i; } sort(a+1,a+n+1,cmp); sort(b+1,b+n+1,cmp); for(int i=1;i<=n;i++) c[b[i].ind]=a[i].ind; msort(1,n); printf("%d",ans%mod); return 0; }
相关文章推荐
- [NOIP2013]火柴排队
- NOIP 2013 火柴排队 (证明+乱搞之后的逆序对)
- 【NOIP2013提高组】火柴排队
- NOIP2013 火柴排队
- NOIP 2013 火柴排队 题解(离散化+树状数组)
- NOIP2013 火柴排队
- NOIP提高组2013 火柴排队
- Noip提高2013 Day1 T2 火柴排队 归并求逆序对
- 归并排序求逆序对 CODEVS 1688 && NOIP 2013 火柴排队
- Noip2013 Day1 T2 火柴排队(归并排序/树状数组 求逆序对)
- [noip2013tg] 火柴排队
- [NOIP2013]火柴排队
- 【NOIP 2013 DAY.1】火柴排队【codevs 3286】
- NOIP2013火柴排队
- 【noip 2013】火柴排队
- NOIP 2013 T2 火柴排队 ---->求逆序对
- noip2013 火柴排队 树状数组
- NOIP2013提高组 火柴排队 (分治逆序对)
- noip2013 火柴排队
- 【洛谷P3370】【NOIP2013】 火柴排队