hdu 4911 Inversion (逆序数变换)
2014-08-06 09:34
435 查看
归并排序求逆序数模板,O(nlogn)的分治算法。
题意:
求k次选择任意两个相邻数交换后得到的数列的最小逆序数。
算法:
当逆序数大于0时,交换任意两个相邻的数交换后,逆序数减1。
这样才能得到最小逆序数。
故答案为max(0LL,inversion)。
========================华丽的分界线==================
用树状数组求逆序数模板
原理:把数列按数从大到小排序,如果有相同大小的数,则按位置从大到小排序。
然后从大数开始插入(它读入时对应的位置),每次插入前统计该位置之前数的个数。
因为是从大到小插入的,所以如果比它大且位置靠前的数与它就能构成一组逆序数。
题意:
求k次选择任意两个相邻数交换后得到的数列的最小逆序数。
算法:
当逆序数大于0时,交换任意两个相邻的数交换后,逆序数减1。
这样才能得到最小逆序数。
故答案为max(0LL,inversion)。
#include<cstdio> #include<iostream> #include<cstring> #define maxn 100005 using namespace std; int a[maxn],tar[maxn]; typedef long long ll; ll res; void solve(int *a,int l,int m,int r) { int l1=l,l2=m+1,c=0; while(l1<=m && l2<=r) { if(a[l1]<=a[l2]) tar[c++] = a[l1++]; else { tar[c++] = a[l2++]; res += m-l1+1; } } while(l1<=m) tar[c++] = a[l1++]; while(l2<=r) tar[c++] = a[l2++]; for(int i=l,j=0;i<=r;i++,j++) a[i] = tar[j]; } void merge_sort(int *a,int l,int r) { if(l>=r) return ; int mid = (l+r)>>1; merge_sort(a,l,mid); merge_sort(a,mid+1,r); solve(a,l,mid,r); } ll max(ll a,ll b) { return a>=b?a:b; } int main() { int n,k; ll ans; while(scanf("%d%d",&n,&k)!=EOF) { for(int i=0;i<n;i++) scanf("%d",&a[i]); res = 0; merge_sort(a,0,n-1); ans = max(res-k,0LL); printf("%I64d\n",ans); } return 0; }
========================华丽的分界线==================
用树状数组求逆序数模板
原理:把数列按数从大到小排序,如果有相同大小的数,则按位置从大到小排序。
然后从大数开始插入(它读入时对应的位置),每次插入前统计该位置之前数的个数。
因为是从大到小插入的,所以如果比它大且位置靠前的数与它就能构成一组逆序数。
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #define maxn 100010 using namespace std; struct node { int v,id; }s[maxn]; int c[maxn],n; typedef long long ll; ll res; bool cmp(node x,node y) { return ((x.v>y.v) || ((x.v==y.v)&&(x.id>y.id))); } int Lowbit(int x) { return x&(x^(x-1)); } ll Getsum(int pos) { ll ret = 0LL; while(pos>0) { ret+=c[pos]; pos -= Lowbit(pos); } return ret; } ll update(int pos) { while(pos<=n) { c[pos]++; pos+=Lowbit(pos); } } int main() { int k,x; while(scanf("%d%d",&n,&k)!=EOF) { memset(c,0,sizeof(c)); res = 0; for(int i=1;i<=n;i++) { scanf("%d",&s[i].v); s[i].id = i; } sort(s+1,s+n+1,cmp); for(int i=1;i<=n;i++) { res += Getsum(s[i].id); update(s[i].id); } printf("%I64d\n",max(res-k,0LL)); } return 0; }
相关文章推荐
- HDU 4911 Inversion(归并排序求逆序数)
- hdu 4911 Inversion 多校第五场 求逆序数
- 2014多校第五场1001 || HDU 4911 Inversion (归并求逆序数)
- hdu 4911 Inversion (分治 归并排序 求逆序数)
- HDU 4911 Inversion 树状数组求逆序数对
- HDU 4911 Inversion 解题报告(逆序数)
- 【树状数组】hdu 4911 Inversion(离散化+树状数组求逆序数)
- hdu 4911 Inversion(求逆序数)
- hdu 4911 Inversion 树状数组求逆序数对
- hdu 4911 Inversion (多校第5场,求逆序数对,离散化)
- HDU 4911 Inversion 求逆序数对
- HDU 4911 Inversion 树状数组求逆序数对
- hdu 1394 Minimum Inversion Number 逆序数/树状数组
- hdu1394 Minimum Inversion Number 逆序数、最小逆序数
- hdu 1394 Minimum Inversion Number || ZOJ Monthly, January 2003 || 线段树 + 逆序数
- HDU 4911 Inversion
- HDU 1394 Minimum Inversion Number (线段树+最小逆序数)
- HDU 4911 ( Inversion )
- HDU 1394 Minimum Inversion Number (线段树 单点更新 求逆序数)
- ACM 逆序对 hdu 4911 Inversion 离散化 树状数组模板