CodeVS3286 NOIP2013 火柴排队
2016-10-24 21:45
232 查看
题目
http://codevs.cn/problem/3286/题解
思想性较强的一道题。显然,最终排成这样一定能让距离和最小:假如a[i]在整个a序列中排行第k大,那么b[i]在整个序列b中排行也是第k大。
假设已经排成上述情形,你会发现不管你怎样交换,都一定会使距离和增大。
于是我们将a序列离散,把原来a里的元素修改为它是第几大,b数组做同样的操作。因为题目说同一序列元素互异,所以a和b中的元素都是1到N。
那么问题就变成,每次只允许交换相邻元素,最少交换几次能是b序列变成a序列。
我们可以把a[i]与i一一映射,那么table[a[i]]=i表示a[i]这个数应该在第i个位置。
那么将b[i]赋值成table[b[i]],表示这个元素排序后应该最终在第几位。
归并求逆序对就好了。
代码
//归并求逆序对 #include <cstdio> #include <algorithm> #include <map> #define maxn 100010 using namespace std; int a1[maxn], a2[maxn], b[maxn], c[maxn], N; long long cnt; map<int,int> table; void pai(const int l, const int r, int *a) { if(l==r)return; int i, j, mid=l+r>>1, p; pai(l,mid,a),pai(mid+1,r,a); for(i=l;i<=mid;i++)b[i]=a[i]; for(i=mid+1;i<=r;i++)c[i]=a[i]; for(i=l,j=mid+1,p=l;p<=r;p++) { if(b[i]<=c[j] and i<=mid or j>r)a[p]=b[i++]; else a[p]=c[j++],cnt+=mid-i+1; } } void lisan(int* a) { int i; table.clear(); for(i=1;i<=N;i++)b[i]=a[i]; sort(b+1,b+N+1); for(i=1;i<=N;i++)table[b[i]]=i; for(i=1;i<=N;i++)a[i]=table[a[i]]; } int main() { int i; scanf("%d",&N); for(i=1;i<=N;i++)scanf("%d",a1+i); for(i=1;i<=N;i++)scanf("%d",a2+i); lisan(a1),lisan(a2); table.clear(); for(i=1;i<=N;i++)table[a1[i]]=i; for(i=1;i<=N;i++)a2[i]=table[a2[i]]; pai(1,N,a2); printf("%d\n",cnt%99999997); return 0; }
相关文章推荐
- [noip2013][codevs3286]火柴排队
- Noip 2013 codevs 3286 火柴排队
- Codevs 3286 火柴排队 2013年NOIP全国联赛提高组 树状数组,逆序对
- 【NOIP 2013 DAY.1】火柴排队【codevs 3286】
- 火柴排队(codevs 3286)
- 【求逆序对】CODE[VS] 3286 火柴排队 (树状数组离散化求逆序对)
- codevs 3286 火柴排队
- CODEVS 3286 火柴排队
- codevs 3286 火柴排队
- 火柴排队(codevs 3286)题解
- Codevs 3286 火柴排队
- 【基础练习】【离散化+逆序对】codevs3286 火柴排队题解
- [noip2013]火柴排队 题解
- noip2013火柴排队
- noip2013 火柴排队 树状数组
- NOIP 2013 CODE[VS] 3287 货车运输 倍增LCA + 最大生成树
- NOIP2013火柴排队
- [NOIP2013提高&洛谷P1966]火柴排队 题解(树状数组求逆序对)
- [NOIP 2013]火柴排队 逆序对
- 洛谷 1966 [NOIP2013] 火柴排队 逆序对