hdu 2492 离散化,树状数组,逆序数

来源:互联网 发布:深入理解java 虚拟机 编辑:程序博客网 时间:2024/05/24 05:26

http://acm.hdu.edu.cn/showproblem.php?pid=2492

题目大意:给出n 个数的序列,枚举一个数,然后查找该数 左边大于它的数的个数 a 和小于他的数的个数 b ,查找右边大于他的数的个数 c  和小于他的数的个数 d 。

                 最后,res  = a * d + b * c ;     其实就是一个查找逆序数的过程。

可以用树状数组,和线段树解决。

这里要注意一点,如果给出的数据比较大的情况,数组无法开到这么大,可以用离散化的思想,把数组转化成一个较小的数组。

树状数组:

#include<iostream>#include<algorithm>#include<cmath>#include<cstdio>#include<cstring>using namespace std;# define N 400000int inf = 100000000;int maxx[N],b[N],c[N];int lmin[N],lmax[N],rmin[N],rmax[N];int n;struct A{    int v,index;}a[400000];int cmp(A p1, A p2){    return p1.v < p2.v;}int lowbit(int x){    return x & (-x);}void update(int x, int y){    while(x <= n)    {        c[x] += y;        x += lowbit(x);    }}int getsum(int x){    int ans = 0;    while(x > 0)    {        ans += c[x];        x -= lowbit(x);    }    return ans;}int main(){    int T,i;    scanf("%d",&T);    while(T--)    {        scanf("%d",&n);        memset(c,0,sizeof(c));        for(i =1 ; i <= n; i++)//离散化        {            scanf("%d",&a[i].v);            a[i].index = i;        }        sort(a+1,a+n+1,cmp);        for(i = 1; i <= n; i++)            b[a[i].index] = i;//离散化        for(i = 1; i <= n; i++)        {            lmin[i] = getsum(b[i]);            lmax[i] = i - lmin[i] - 1;            update(b[i],1);        }        memset(c,0,sizeof(c));        for(i = n; i > 0; i--)        {            rmin[i] = getsum(b[i]);            rmax[i] = n-i - rmin[i];            update(b[i],1);        }        long long  res = 0;//第一次  WA  就是因为这个地方,定义的时候用了int        for(i = 1; i <= n; i++)        res += lmin[i] * rmax[i] + lmax[i] * rmin[i];        printf("%I64d\n",res);    }    return 0;}


0 0
原创粉丝点击