hdoj 1394 Minimum Inversion Number【线段树求逆序对】
来源:互联网 发布:网络三大邪书 编辑:程序博客网 时间:2024/05/18 09:12
求逆序对有很多算法,这里说一下线段树求逆序对的思想。
知识点:线段树,逆序对,单点更新,成段求和
算法:线段树求逆序数的前提条件是要离散化,变成连续的点,首先建树,每个节点设置一个num值为0.
然后根据逆序对的定义,前面出现过的比当前数大的个数的和,我们需要求前面的比他大的数,其实就相当于从当前a【i】点对他后面所有出现过的数求和一次。然后把当前点的值在线段树叶子节点变为1,表示出现过,并向上更新到线段树里面。比如说样例4 2 1 5 3
首先4后面没有值,4更新为1,4--5区间更新为1,1--5区间更新为1,
然后2,求3--5区间的和为1,然后把2更新为1,1--2更新为1,1---5更新为2
然后1,求2--5区间和为2,然后把1更新为1,1--2更新为2,1---5更新为3
然后5,求5---5区间和为0,然后把5区间更新为1,4--5区间更新为2,1---5区间更新为4
然后3,求4--5区间和为2.
然后把所有的和相加1+2+2 = 5,就是逆序对的个数,最简单的线段树运用。
对于当前这个题目,要求数组是环形的,可以从任一点开始,求一个最小的逆序数。
那么我们考虑对于当前一个元素移动到后面,它相当于上次求得的逆序数减去比它小的元素a【i】-1,然后加上比他大的元素n-a【i】-1,所以可以枚举求出一个最小值。
代码:
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int N = 101000;int a[N];struct Node{ int l,r,num;};Node tree[4*N];void build(int l,int r,int o){ tree[o].l=l,tree[o].r=r; tree[o].num=0; if(l==r) return ; int mid=(l+r)>>1; build(l,mid,o<<1); build(mid+1,r,o+o+1);}void update(int t,int o){ if(tree[o].l==tree[o].r && tree[o].l==t) { tree[o].num++; return ; } int mid=(tree[o].l+tree[o].r)>>1; if(t>mid) update(t,o+o+1); else update(t,o+o); tree[o].num=tree[o+o].num+tree[o+o+1].num;}int query(int l,int r,int o){ if(tree[o].l==l && tree[o].r==r) { return tree[o].num; } int mid=(tree[o].l+tree[o].r)>>1; if(r<=mid) return query(l,r,o+o); else if(l>mid) return query(l,r,o+o+1); else return query(l,mid,o*2)+query(mid+1,r,o*2+1);}int main(){ //freopen("Input.txt","r",stdin); int n; while(~scanf("%d",&n)) { for(int i=0;i<n;i++){ scanf("%d",&a[i]); a[i]++; } build(1,n,1); int ans=0; for(int i=0;i<n;i++) { ans+=query(a[i],n,1); update(a[i],1); } int sum=ans; for(int i=0;i<n;i++) { sum+=n-a[i]-a[i]+1; //printf("%d\n",sum); ans=min(ans,sum); } printf("%d\n",ans); } return 0;}
0 0
- hdoj 1394 Minimum Inversion Number【线段树求逆序对】
- hdu 1394 Minimum Inversion Number(线段树求逆序对)
- HDU 1394 Minimum Inversion Number (线段树 求逆序对)
- HDOJ 1394 - Minimum Inversion Number 求逆序对+二分查找
- HDOJ 1394 Minimum Inversion Number(逆序数 + 线段树)
- HDOJ 1394 Minimum Inversion Number(线段树+逆序数)
- HDOJ 1394 Minimum Inversion Number 求循环串的最小逆序数(暴力&&线段树)
- 【线段树-区间求和求最小逆序数】HDOJ Minimum Inversion Number 1394
- 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(线段树求逆序数)
- hdu 1394 Minimum Inversion Number 线段树求逆序数
- hdu 1394 Minimum Inversion Number 线段树求逆序数
- HDU 1394 Minimum Inversion Number(线段树求逆序数)
- 开源 免费 java CMS - FreeCMS2.0 会员密码设置
- 缓冲类实例
- Java多线程例子讲解
- openstack neutron L3 HA
- 这一计划将编译
- hdoj 1394 Minimum Inversion Number【线段树求逆序对】
- 私有的成员能被子类继承吗?
- 每个返回类型
- 跨域问题解决方案
- spring的jar各包作用
- 使用sql语句查询日期在一周内的数据
- AppFuse 3的乱码问题
- eclipse自带内存监视及回收插件Hidden Heap Status
- LInux 大括号扩展