hdu 1394 Minimum Inversion Number
2011-04-15 10:30
330 查看
首先,我们可以把初始序列的逆序对数求出来(暴力,线段树,树状数组什么的都可以),然后根据序列特殊的性质进行O(N)的转移和更新
先说下线段树怎么求逆序对把,本质上还是用了树状数组的思想,首先建立一个线段树,每个线段上储存一个sum值,表示这个线段上的所有数总共出现的次数,于是我们每读到一个数ai,就去查询[ai+1,n](注意ai=n的情况)这个区间上在读入前i-1个数后的sum值,这个就是第i个数对全局逆序对数的贡献
然后,对[ai,ai]这个区间进行更新,sum值加1,并向上递归更新父区间
由于n个数的特殊性,分别是[0,n-1]中的n个数,每个数都出现一次,且无重复
那么,我们每次把当前第一个数a移到最后一个时,逆序对数减少x个,同时又增加y个
其中,x等于[0,n-1]中比a小的个数,y等于[0,n-1]中比a大的个数
于是,就是进行O(N)的转移和更新答案了
代码:
先说下线段树怎么求逆序对把,本质上还是用了树状数组的思想,首先建立一个线段树,每个线段上储存一个sum值,表示这个线段上的所有数总共出现的次数,于是我们每读到一个数ai,就去查询[ai+1,n](注意ai=n的情况)这个区间上在读入前i-1个数后的sum值,这个就是第i个数对全局逆序对数的贡献
然后,对[ai,ai]这个区间进行更新,sum值加1,并向上递归更新父区间
由于n个数的特殊性,分别是[0,n-1]中的n个数,每个数都出现一次,且无重复
那么,我们每次把当前第一个数a移到最后一个时,逆序对数减少x个,同时又增加y个
其中,x等于[0,n-1]中比a小的个数,y等于[0,n-1]中比a大的个数
于是,就是进行O(N)的转移和更新答案了
代码:
#include<iostream> #include<string> #include<cstdio> #include<algorithm> #include<math.h> #include<stack> #include<queue> #include<vector> using namespace std; const int MAX=5005; const int inf=1<<30; struct node { int l,r,sum; }t[MAX*5]; int val[MAX]; int n; void build(int ll,int rr,int n) { t .l=ll; t .r=rr; t .sum=0; if(ll==rr) return; int mid=(ll+rr)/2; build(ll,mid,n*2); build(mid+1,rr,n*2+1); } void update(int ll,int rr,int n) { if(t .l==ll&&t .r==rr) { t .sum++; return; } int mid=(t .l+t .r)/2; if(mid>=rr) update(ll,rr,n*2); else update(ll,rr,n*2+1); t .sum=t[n*2].sum+t[n*2+1].sum; } int query(int ll,int rr,int n) { if(t .l==ll&&t .r==rr) { return t .sum; } int mid=(t .l+t .r)/2; if(mid>=rr) return query(ll,rr,n*2); else if(mid<ll) return query(ll,rr,n*2+1); else return query(ll,mid,n*2)+query(mid+1,rr,n*2+1); } int main() { int i,j,res; while(scanf("%d",&n)!=EOF) { build(1,n,1); res=0; for(i=1;i<=n;i++) { scanf("%d",&val[i]); val[i]++; if(val[i]==n) { //update(n,n,1); j=0; res+=j; } else { j=query(val[i]+1,n,1); res+=j; } update(val[i],val[i],1); //cout<<"i="<<i<<endl; //cout<<"j="<<j<<endl; } int ans=res; for(i=1;i<=n;i++) { res=res-(val[i]-1)+(n-val[i]); ans=min(res,ans); } printf("%d/n",ans); } return 0; }
相关文章推荐
- 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
- Minimum Inversion Number HDU-1394
- HDU 1394 Minimum Inversion Number (BIT入门)
- 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 树状数组
- HDU1394 Minimum Inversion Number
- HDU 1394 Minimum Inversion Number Segment Tree解法
- HDU ~ 1394 ~ Minimum Inversion Number(暴力||归并排序||线段树||树状数组)
- hdu1394 Minimum Inversion Number --更新查询
- hdu 1394 Minimum Inversion Number(树状数组求逆序数)
- hdu 1394 Minimum Inversion Number(线段树)