zoukankan      html  css  js  c++  java
  • hdu-1394(线段树)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1394

    思路:建立一个空线段树,求出逆序数,(逆序数性质:交换两个相邻数,逆序数+1或-1, 交换两个不相邻数a, b, 逆序数+=两者间大于a的个数-两者间小于a的个数)

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    using namespace std;
    const int maxn = 50050;
    int a[maxn*4],n,b[maxn*4];
    void build(int k,int l,int r)
    {
        b[k]=0;
        if(l==r) return ;
        int mid=(l+r)/2;
        build(k*2,l,mid);
        build(k*2+1,mid+1,r);
    }
    void update(int k,int l,int r,int x,int pos)
    {
        if(l==r)
        {
            b[k]+=x;
            return ;
        }
        int mid=(l+r)/2;
        if(pos<=mid) update(k*2,l,mid,x,pos);
        else update(k*2+1,mid+1,r,x,pos);
        b[k]=b[k*2]+b[k*2+1];
    }
    int query(int k,int l,int r,int x,int y)
    {
        if(x<=l&&y>=r) return b[k];
        int mid=(l+r)/2;
        if(y<=mid) return query(k*2,l,mid,x,y);
        if(x>mid) return query(k*2+1,mid+1,r,x,y);
        return query(k*2,l,mid,x,y)+query(k*2+1,mid+1,r,x,y);
    }
    int main(void)
    {
        int i,sum,tmp;
        while(~scanf("%d",&n))
        {
            build(1,1,n);
            sum=0;
            for(i=1;i<=n;i++)
            {
                scanf("%d",&a[i]);
                sum+=query(1,1,n,a[i]+1,n);
                update(1,1,n,1,a[i]+1);
            }
            tmp=sum;
            for(i=1;i<=n;i++)
            {
                sum+=(n-1-a[i]-a[i]);
                if(tmp>sum)
                tmp=sum;
            }
            printf("%d
    ",tmp);
        }
        return 0;
    }
  • 相关阅读:
    Codeforces932E. Team Work
    BZOJ2956: 模积和
    Codeforces932D. Tree
    51nod1040 最大公约数之和
    伯努利数
    BZOJ3456: 城市规划
    BZOJ4555: [Tjoi2016&Heoi2016]求和
    Codeforces936C. Lock Puzzle
    BZOJ3771: Triple
    SPOJ LCS2 后缀自动机
  • 原文地址:https://www.cnblogs.com/2018zxy/p/9858649.html
Copyright © 2011-2022 走看看