HDU1394 Minimum Inversion Number
2017-02-16 21:40
337 查看
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=1394题解:
题目大意:给出n个数字(从0到n-1),题目给出的时候顺序已经打乱了,让你算出这些数字按题目移动构成最小的逆序数。(不会逆序数的谷歌一下)
这里我先讲下暴力的方法,先按逆序数的定义,先暴力的求出总和sum ,因为题目中一般都是把第一个数直接放在了最后,所以我们先假设要移动的数字为xi,那么比xi小的数字有xi,比xi大的数字有n-1-xi(因为数字的范围是0到n-1的),那么进行变化以后的sum应该为sum=sum-low(xi)+up(xi)。因为原本比xi要大的数字把xi放到后面以后就会构成了逆序列,从而增加了逆序数的数量。同理可得比xi要小的。因为数据的范围比较小,因此我们可以直接暴力来做。
暴力代码:
#include <cmath> #include <cstdio> #include <map> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define met(a,b) memset(a,b,sizeof(a)) #define inf 0x3f3f3f3f typedef long long ll; const ll maxn = 5000+10; int num[maxn]; int main() { int n; while(cin>>n) { for(int i=0;i<n;i++) cin>>num[i]; int sum=0; for(int i=0;i<n;i++) for(int j=i+1;j<n;j++) if(num[i]>num[j]) sum++; int temp=sum; for(int i=0;i<n;i++) { temp=temp-num[i]+n-1-num[i];//sum=sum-low(num[i])+up(num[i]) sum=min(temp,sum); } cout<<sum<<endl; } }
本题还可以用线段树来进行优化,但是线段树优化的只是前面的暴力的代码,将原来n^2的代码优化到了n*log(n)的时间,优化的可以看作是是暴力代码中的第二个for。
线段树代码:
#include <cmath> #include <cstdio> #include <map> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define met(a,b) memset(a,b,sizeof(a)) #define inf 0x3f3f3f3f typedef long long ll; const ll maxn = 5000+10; #define lchild rt << 1, l, m #define rchild rt << 1 | 1, m + 1, r int tree[maxn<<2]; int x[maxn]; void push_up(int rt) { tree[rt]=tree[rt << 1]+tree[rt << 1 | 1]; } void build(int rt,int l,int r) { tree[rt]=0; if(l==r) return; int m=(l+r)>>1; build(lchild); build(rchild); push_up(rt); } void updata(int pos,int rt,int l,int r) { if(l==r) { tree[rt]++; return; } int m=(l+r)>>1; if(pos<=m) updata(pos,lchild); else updata(pos,rchild); push_up(rt); } int query(int L,int R,int rt,int l,int r) { if(L<=l&&R>=r) return tree[rt]; int m=(l+r)>>1; int ret=0; if(L<=m) ret+=query(L,R,lchild); if(R>m) ret+=query(L,R,rchild); return ret; } int main() { int n; while(cin>>n) { build(1,0,n-1); int sum=0; for(int i=0;i<n;i++) { cin>>x[i]; sum+=query(x[i],n-1,1,0,n-1); updata(x[i],1,0,n-1); } int temp=sum; for(int i=0;i<n;i++) { temp+=n-1-x[i]-x[i]; sum=min(temp,sum); } cout<<sum<<endl; } }
4000
相关文章推荐
- hdu-1394- Minimum Inversion Number--- 线段树优化
- hdu 1394 Minimum Inversion Number (树状数组)
- hdu 1394 Minimum Inversion Number(树状数组求逆序数)
- hdu 1394 Minimum Inversion Number || ZOJ Monthly, January 2003 || 线段树 + 逆序数
- hdu 1394 Minimum Inversion Number(线段树求逆序对)
- hdu 1394 Minimum Inversion Number(线段树)
- HDU - 1394 Minimum Inversion Number(树状数组 or 线段树)
- hdu 1394 Minimum Inversion Number
- HDU 1394 Minimum Inversion Number (求逆序对数)
- 线段树求逆序数 hdu 1394 Minimum Inversion Number
- HDU 1394 Minimum Inversion Number(求逆序对+线段树||归并排序)
- hdu 1394 Minimum Inversion Number(线段树)
- HDU 1394 Minimum Inversion Number
- HDU 1394 Minimum Inversion Number
- 线段树专题#5_蒟蒻训练历程记录_HDU 1394 Minimum Inversion Number_单点更新+思维转换
- HDU Problem 1394 Minimum Inversion Number【树状数组】
- HDU 1394 Minimum Inversion Number( 归并排序 & 线段树 )
- hdu 1394 Minimum Inversion Number
- Hdu 1394 Minimum Inversion Number(线段树或树状数组)
- hdu 1394 Minimum Inversion Number(线段树or树状数组)