【uva】1428 - Ping pong(树状数组)

来源:互联网 发布:天气预报软件哪个好 编辑:程序博客网 时间:2024/06/05 03:24

周五需要检测 树状数组以及线段树,这几天猛练一下,晚上看了一下二叉索引树,感觉还可以理解,不过A题的还是很有难度的。

题意给的很明显了,给一个位置i,求这个位置左边和右边比它小的数的个数(求出小的,求大的用减就可以了,因为a[i]的值都不重复.

我们从左往右检查,我们用一个数组vis[i]记录i值是否出现过(出现过为1,没出现为0),那么遍历到a[i]的时候我们只需要求 vis[1] + vis[2] + ……+vis[a[i] - 1],这样每次我们都需要花大量时间进行查询,其次,加入你使用C[i] 代表 vis[1] + vis[2] + …… +vis[i],那么,每次更行a[i],你都需要更新C[j] ( j > a[i]),非常耗费时间。因此使用上了树状数组。

如果进行查询操作,求vis[1] + vis[2] + vis[x];

int Sum(int x){    /*求和的话向左边走*/    int ans = 0;    while(x > 0){        ans += C[x];        x -= lowbit(x);    }    return ans;}

如果进行插入,该表vis的值

int Add(int x,int d){    while(x < MAXD){        C[x] += d;        x += lowbit(x);    }}

此外,lowbit(x) = x & -x;

这题经过计算数据范围需要使用long long 表示

#include<cstdio>#include<cstring>#include<iostream>using namespace std;#define MAXD 100000 + 10typedef long long LL;int array[MAXD];int C[MAXD];int lowbit(int x){    return x & -x;}int Sum(int x){    /*求和的话向左边走*/    int ans = 0;    while(x > 0){        ans += C[x];        x -= lowbit(x);    }    return ans;}int Add(int x,int d){    while(x < MAXD){        C[x] += d;        x += lowbit(x);    }}int main(){    int T;    scanf("%d",&T);    while(T--){        int n;        int vis[MAXD]; /*记录i是否存在*/        int c[MAXD],d[MAXD];        memset(vis,0,sizeof(vis));        memset(C,0,sizeof(C));        scanf("%d",&n);        for(int i = 1 ; i <= n ; i++)            scanf("%d",&array[i]);        for(int i = 1 ; i <= n ; i++){  /*左边比a[i]小的数个数*/            int t = array[i];            if(!vis[t]){                vis[t] = 1;                Add(t,1);            }            c[i] = Sum(t) - 1;        }        memset(C,0,sizeof(C));        memset(vis,0,sizeof(vis));        for(int i = n ; i >= 1; i--){  /*右边比a[i]小的数个数*/            int t = array[i];            if(!vis[t]){                vis[t] = 1;                Add(t,1);            }            d[i] = Sum(t) - 1;        }        LL ans = 0;        for(int i = 1 ; i <= n ; i++){            ans = ans + c[i] * (n - i - d[i]) + (i - 1 - c[i]) * d[i];        }        printf("%lld\n",ans);    }    return 0;}


0 0
原创粉丝点击