HDU 1394 Minimum Inversion Number(线段树)

来源:互联网 发布:mysql error1054 编辑:程序博客网 时间:2024/05/17 06:25

如果 i<j  a[i]>a[j] 就是倒置数 ,然后从原始序列,把首元素依次后移,形成的新序列,求出每个队列的倒置数的对数,要注意的一点就是如果首元素为3,最大元素为10,将3移到最后,倒置数则增加了7个(45678910),减少了2个(12),所以由第一个序列的倒置数可以推出循环右移后的序列的倒置数对数,详细看代码注释


题目链接 点击打开链接


代码注释:


<strong><span style="font-size:18px;color:#ff6600;">#include<iostream>#include<algorithm>#include<cstdio>using namespace std;#define N 5000+10struct node{    int l,r,sum;} a[N*3];int s[N];void build(int l,int r,int i){    a[i].l=l;    a[i].r=r;    a[i].sum=0;    if(l==r)        return ;    int mid=(l+r)/2;    build(l,mid,2*i);    build(mid+1,r,2*i+1);}void update(int l,int i){    a[i].sum++;  //每个元素进来标记一下    if(a[i].l==a[i].r)        return ;    int mid=(a[i].l+a[i].r)/2;    if(l<=mid)        update(l,2*i);    else        update(l,2*i+1);}int query(int l,int r,int i){    if(a[i].l==l&&a[i].r==r)        return a[i].sum;    int mid=(a[i].l+a[i].r)/2;    if(r<=mid)        return query(l,r,2*i);    else if(l>mid)        return query(l,r,2*i+1);    else        return query(l,mid,2*i)+query(mid+1,r,2*i+1);}int main(){    int n,i;    while(cin>>n)    {        build(1,n,1);        int sum=0;        for(i=1; i<=n; i++)        {            scanf("%d",&s[i]);            sum+=query(s[i]+1,n,1);//这里记数原理就是加上每个元素后面的数出现的次数,出现的次数在update里开头可以记数            update(s[i]+1,1);        }        int ans=sum;        for(i=1; i<=n; i++)        {            sum+=n-s[i]-1-s[i];            ans=min(sum,ans);        }        cout<<ans<<endl;    }}</span></strong>


0 0