zoukankan      html  css  js  c++  java
  • hdu 1094 所想到的

      本来是想练一下线段树的,看到这题逆序对,不用下树状数组都可惜了啊!

      用树状数组很简单,就中间有一个细节,因为数组中是有0的,在我进行区间求和的时候,判断条件是x>=0,而lowb(0)==0,这就会使程序陷入死循环!注意!

      因为这题是求数组a位置i右边比a[i]大的数的个数,按照网上的说法(http://apps.hi.baidu.com/share/detail/16352612):

      如果要求b[i] = 位置i左边大于等于a[i]的数的个数呢?当然我们可以离散化时倒过来编号,但有没有更直接的方法呢?答案是有。几乎所有教程上树状数组的三个函数都是那样写的,但我们可以想想问啥修改就是x不断增加,求和就是x不断减少,我们是否可以反过来呢,答案是肯定的。代码如下:

     

    代码
    void Update(int x, int c)
    {
    int i;
    for (i = x; i >= 1; i -= Lowbit(i))
    {
    tree[i]
    += c;
    }
    }

    int Getsum(int x)
    {
    int i;
    int temp(0);
    for (i = x; i < maxn; i += Lowbit(i))
    {
    temp
    += tree[i];
    }
    return temp;
    }

      今天我写程序运行了一下,感觉这个观点并不是对的。我们应该还记得树状数组那张标志性的图(可以去看看):

        树状数组之所以快,是因为它的结构很好,它的C[4]表示前4个数,C[8]表示前8个数……再写博客的时候,突然觉得是对的。它的修改时往下修改,每一个比它小的数都会有+1的,也只有比它小的才有+1。而求和的话是看比这个数大的数在前面出现几次,在修改操作中已经确定,这个是符合前面的逻辑的!

     

      带上1094的树状数组代码吧: 

    代码
    #include <iostream>
    #include
    <cstdio>
    using namespace std;
    #define min(c,d) (c>d?d:c)

    int n,S,mmin;
    int C[5005];
    int a[5005];

    int lowb(int t)
    {
    return t&(-t);
    }

    void up(int i,int val)
    {
    for(;i<=n;i+=lowb(i))
    {
    C[i]
    += val;
    }
    }

    int down(int i)
    {
    int sum = 0;
    for(;i>0;i-=lowb(i))
    {
    sum
    += C[i];
    }
    return sum;
    }

    void Init()
    {
    int i;
    S
    = 0;
    memset(C,
    0,sizeof(C));
    for(i=1;i<=n;i++)
    {
    scanf(
    "%d",&a[i]);
    a[i]
    += 1; //因为有0的存在,在求和的时候判断条件是i>=0,会陷入死循环,所以加1
    }

    }

    void Play()
    {
    int i;
    for(i=n;i>=1;i--)
    {
    S
    += down(a[i]);
    up(a[i],
    1);
    }

    mmin
    = S;
    for(i=1;i<=n;i++)
    {
    S
    = S - (a[i] - 1) //移动前左边比a[i]小的数
    + (n - a[i]); //移动后右边比a[i]大的数
    mmin = min(mmin,S);
    }
    }

    void print()
    {
    printf(
    "%d\n",mmin);
    }

    int main()
    {
    while(scanf("%d",&n)!=EOF)
    {
    Init();
    Play();
    print();
    }
    }

      线段树代码:

    代码
    #include <iostream>
    #include
    <cstdio>
    using namespace std;

    #define min(c,d) (c>d?d:c)
    const long maxn = 5005;

    int n;
    int mmin;
    int a[maxn];

    struct node
    {
    int l;
    int r;
    int sum;
    }inv[maxn
    *4];

    void CreateTree(int ini,int a,int b)
    {
    inv[ini].l
    = a;
    inv[ini].r
    = b;
    inv[ini].sum
    = 0;

    if(a == b)
    return;

    int mid = (a+b) >> 1;
    CreateTree(ini
    *2,a,mid);
    CreateTree(ini
    *2+1,mid+1,b);
    }

    void Updata(int ini,int x,int val)
    {
    if(inv[ini].l == x && inv[ini].r == x)
    {
    inv[ini].sum
    += val;
    return;
    }

    int mid = (inv[ini].l + inv[ini].r) >> 1;

    if(x <= mid)
    {
    Updata(ini
    *2,x,val);
    inv[ini].sum
    += val;
    }
    else
    {
    Updata(ini
    *2+1,x,val);
    inv[ini].sum
    += val;
    }
    }

    int Find(int ini,int x,int y)
    {
    if(inv[ini].l == x && inv[ini].r == y)
    {
    return inv[ini].sum;
    }

    int mid = (inv[ini].l + inv[ini].r) >> 1;

    if(y <= mid)
    {
    return Find(ini*2,x,y);
    }
    else if(x > mid)
    {
    return Find(ini*2+1,x,y);
    }
    else
    {
    return Find(ini*2,x,mid) + Find(ini*2+1,mid+1,y);
    }
    }
    void Init()
    {
    int i;
    for(i=0;i<n;i++)
    {
    scanf(
    "%d",&a[i]);
    }
    }

    void Play()
    {
    int i;
    int sum = 0;
    CreateTree(
    1,0,n);
    for(i=n-1;i>=0;i--)
    {
    sum
    += Find(1,0,a[i]);
    Updata(
    1,a[i],1);
    }

    mmin
    = sum;
    for(i=0;i<n;i++)
    {
    sum
    = sum - a[i] + (n-a[i]-1);
    mmin
    = min(mmin,sum);
    }
    }

    void print()
    {
    printf(
    "%d\n",mmin);
    }

    int main()
    {
    while(scanf("%d",&n)!=EOF)
    {
    Init();
    Play();
    print();
    }
    }

  • 相关阅读:
    接口自动化测试中解决所遇问题的博客链接
    python中logging日志模块详解
    yaml.load()时总是出现警告:YAMLLoadWarning: calling yaml.load() without Loader=...
    基于ArcGIS Desktop 10.2开发的环境安装
    【部署】IIS导入证书后绑定报错“证书中的一个或多个中间证书丢失”
    IIS7.x 生成CSR证书请求文件
    Sql Server多种分页性能的比较
    网页上出现D盾拦截,删除、取消
    Fusioncharts图表常用参数设置
    Windows Server 2016 安装.NET Framework 3.5 错误
  • 原文地址:https://www.cnblogs.com/silencExplode/p/1880352.html
Copyright © 2011-2022 走看看