数据结构 线段树 hdu1394 Minimum Inversion Number(单点更新)

来源:互联网 发布:树莓派gpio编程工具 编辑:程序博客网 时间:2024/05/21 17:10

题意:给一串数,当依次将第一个数变成最后一个数的过程中,求出最小的 逆序数。

解法:

先建树,全部初始化为0,依次从那串数中取数,添加到树中,用树来快速找出,在树中比这个数大的数的个数,累加起来。

1.每当第一个数放到最后的时候,逆序数因为后移而减少a[i],放到最后增加n-1-a[i]。

2.当然也可以每移动一次去求,在树中比这个数大的个数 去累计。

#include <stdio.h>#include <string.h>#include <cstring>#include <algorithm>#include <iostream>using namespace std;const int N=5005;int sum[N<<2];void PushUP(int rt){sum[rt]=sum[rt<<1]+sum[rt<<1|1];}void build(int l,int r,int rt){//建树,全都初始化为0 sum[rt]=0;if(l==r) return ;int m=(l+r)>>1;build(l,m,rt<<1);build(m+1,r,rt<<1|1);}void update(int p,int l,int r,int rt){//每更新一次,点p所在位置 增1; if(l==r){sum[rt]++;return ;}int m=(l+r)>>1;if(p<=m) update(p,l,m,rt<<1);else update(p,m+1,r,rt<<1|1);PushUP(rt);}int query(int L,int R,int l,int r,int rt){if(L<=l && r<=R){return sum[rt];}int m=(l+r)>>1;int ret=0;if(L<=m) ret+=query(L,R,l,m,rt<<1);if(R>m) ret+=query(L,R,m+1,r,rt<<1|1);return ret;}int x[N];int main(){int n;    while(~scanf("%d",&n))    {    //建树,每个点都初始化为0     build(0,n-1,1);int  Sum=0;for(int i=0;i<n;i++){scanf("%d",&x[i]);//询问 树中 第x[i]位置 到最后。累计比x[i]大的个数 Sum+=query(x[i],n-1,0,n-1,1);//在树中插入x[i] update(x[i],0,n-1,1);}//用来存储最小值 int ret=Sum;//printf("--%d\n",Sum); for(int i=0;i<n;i++){Sum+=n-1-x[i]-x[i];//printf("==%d\n",Sum);ret=min(ret,Sum);}    printf("%d\n",ret);    }    return 0;}


0 0
原创粉丝点击