zoukankan      html  css  js  c++  java
  • POJ 2299 树状数组+离散化求逆序对

    给出一个序列 相邻的两个数可以进行交换 问最少交换多少次可以让他变成递增序列 每个数都是独一无二的

    其实就是问冒泡往后 最多多少次

    但是按普通冒泡记录次数一定会超时

    冒泡记录次数的本质是每个数的逆序数相加 因为只有后面的数比自己笑才能交换

    但是暴力求逆序数也会超时

    于是用树状数组求 从最后往前看 每次求sum相加

    但是数据的范围根本开不出来树状数组...

    但是由于n最多只有五十万 所以把它离散化一下 把这n个数变成1~n

    技巧就是先按大小排序 然后把他们变成1~n 然后按照结构体中的顺序再排回来

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<map>
    #include<math.h>
    using namespace std;
    struct node
    {
        int zhi;
        int whe;
    };
    int n;
    int cmp(node a,node b)
    {
        return a.zhi<b.zhi;
    }
    int c[500050];
    node a[500050];
    int lowbit(int x)
    {
        return x&(-x);
    }
    long long  sum(int x)
    {
        long long sum=0;
        for(int i=x;i>=1;i-=lowbit(i))
        {
            sum+=c[i];
        }
        return sum;
    }
    
    void add(int x)
    {
        for(int i=x;i<=n;i+=lowbit(i))
        {
            c[i]+=1;
        }
    }
    int cmpp(node a,node b)
    {
        return a.whe<b.whe;
    }
    int main(){
    while(~scanf("%d",&n))
    {
        if(n==0)
            break;
        memset(c,0,sizeof(c));
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i].zhi);
            a[i].whe=i;
        }
        sort(a+1,a+1+n,cmp);
        for(int i=1;i<=n;i++)
        {
            a[i].zhi=i;
        }
        sort(a+1,a+1+n,cmpp);
        long long ans=0;
        for(int i=n;i>=1;i--)
        {
            long long summ=sum(a[i].zhi);
            add(a[i].zhi);
            ans+=summ;
        }
        printf("%I64d
    ",ans);
    }
    }
    

      

  • 相关阅读:
    Unity Technologies-提供全面的技术支持服务
    Unity 大中华区核心业务
    帕斯卡(pascal)命名法:
    骆驼命名法
    匈牙利命名法
    软件分类
    模型规范
    命名规范
    22. Generate Parentheses 生成括号
    421. Maximum XOR of Two Numbers in an Array 数组中两个数的最大异或
  • 原文地址:https://www.cnblogs.com/rayrayrainrain/p/5271922.html
Copyright © 2011-2022 走看看