zoukankan      html  css  js  c++  java
  • 用线段树求逆序数。。。 突然发现自己的单点更新以及自己区间查询还是有点问题。,。

    这里先统一一下单点更新以及区间查询问题吧  统一使用全局变量 

    区间查询的话 目的区间用全局变量x y表示 然后从第一层开始 不断向下层搜(也就是不断的二分的过程)

    先说说平时怎么求逆序数把  在每次读入一个数的时候 记录前面比他大的数就是目前的逆序数

    那么 怎么用线段树来实现呢 首先 我们需要建一个空树 每个节点记录这个区间里面出现数的个数(sum)然后再按顺序读入数列的时候 查询在读入这个数之前有多个个比他大的数 即查询(x+1,n-1)这个区间有多少值 然后单点更新刚读入的值

    #include<cstdio>
    #include<string.h>
    #include<iostream>
    #define maxn 5001
    using namespace std;
    struct node
    {
        int l,r,sum;
    }stu[maxn*4];
    int n;
    int arr[maxn];
    int x,y;
    void build(int l,int r,int i)
    {
        stu[i].l=l;
        stu[i].r=r;
        stu[i].sum=0;
        if(l==r) return;
        int mid=(l+r)/2;
        build(l,mid,i<<1);
        build(mid+1,r,i<<1|1);
    }
    int que(int i)
    {
        if(x<=stu[i].l&&stu[i].r<=y)    return stu[i].sum;
        int mid=(stu[i].l+stu[i].r)/2;
        int sum1=0,sum2=0;
        if(x<=mid) sum1=que(i*2);
        if(y>mid) sum2=que(i*2+1);
        return sum1+sum2; 
    }
    void updata(int i)
    {
        int l=stu[i].l;
        int r=stu[i].r;
        if(l==r)
        {
            stu[i].sum++;
            return;
        }
        int mid=(l+r)/2;
        if(x<=mid) updata(i<<1);
        else updata(i<<1|1);
        stu[i].sum=stu[i*2].sum+stu[i*2+1].sum;
    }
    int main()
    {
        while(cin>>n)
        {
            build(0,n-1,1);
            int sum=0;
            for(int i=0;i<n;i++) 
            {
                cin>>arr[i];
                x=arr[i];
                y=n-1;
                sum+=que(1);//统计每次插入时候的逆序数
                updata(1);
            }
            int ans=sum;
            for(int i=0;i<n;i++)
            {
                sum=sum+n-2*arr[i]-1;
                /*
                  因为序列为[0, n-1],若最前面一个数为x,序列中比x
                  小的数为[0, x-1], 共x个,比x大的数为[x+1, n-1],
                  共n-x-1个,将x移到最后,比x小的数的逆序数均减1,
                  x的前面比x大的数有n-x-1个,x的逆序数增加n-x-1。
                  所以新序列的逆序数为原序列的逆序数加上n-2*x-1。
                */
    

    if(ans>sum) ans=sum; } cout<<ans<<endl; } return 0;
  • 相关阅读:
    bootstrap-图片样式记录
    关于json数据中的多反斜杆转译--StringEscapeUtils.unescapeJava(踩过的坑)
    Nginx与tomcat组合的简单使用
    多进程之间的互斥信号量的实现(Linux和windows跨平台)
    跨平台(win和unix)的线程封装类
    linux 静态库、共享库
    WinMain与wWinMain,win32的字符集问题
    linux下添加动态链接库路径、动态库加载等方法
    win系统动态载入DLL所需要的三个函数详解(LoadLibrary,GetProcAddress,FreeLibrary)
    dll程序开发总结
  • 原文地址:https://www.cnblogs.com/z1141000271/p/5758317.html
Copyright © 2011-2022 走看看