poj 3928 Ping pong(数据结构:树状数组)

来源:互联网 发布:apache漏洞 编辑:程序博客网 时间:2024/04/29 01:11

白书上树状数组例题,感觉看起来太吃力了

设输入为pos[i]

则我们令

c[i]为1-(i-1)这些人中,rank小于pos[i]的人数个数

d[i]为(i+1)到n这些人中,rank小于pos[i]的人数个数

易知答案为所有c[i]*(n-i-d[i])+(i-1-c[i])*d[i]的总和

构造树状数组a[i],代表rank值小于i的人的个数

求解如下:

#include <stdio.h>#include <string.h>#define MAXN 100100#define LL long longint a[MAXN], c[MAXN];int pos[MAXN];int lowbit(int x) {    return x&(-x);}int sum(int x) {    int ans = 0;    while(x > 0) {        ans += a[x];        x -= lowbit(x);    }    return ans;}int add(int x, int d) {    while(x <= MAXN) {        a[x] += d;        x += lowbit(x);    }}int main(void) {    int i, T, N;    LL ts, ans;    scanf("%d", &T);    while(T--) {        scanf("%d", &N);        ans = 0;        memset(a, 0, sizeof(a));        for(i=1; i<=N; ++i) {            scanf("%d", &pos[i]);            add(pos[i], 1);            //更新rank值大于pos[i]的人的个数            c[i] = sum(pos[i]-1);            //统计rank值在1到pos[i]之间人的个数,由循环可知,此时保证在1-(i-1)pos内求解//            printf("c[%d] = %d\n", i, c[i]);        }        for(i=1; i<=N; ++i) {            ts = sum(pos[i]-1);            //统计rank值在11到pos[i]之间人的个数,由循环可知,此时保证在1-n pos内求解,故减去c[i]即为i+1到n pos中rank小于pos[i]的个数//            printf("d[%d] = %d\n", i, ts-c[i]);            ans += c[i]*(N-i-(ts-c[i]));            ans += (i-1-c[i])*(ts-c[i]);        }        printf("%lld\n", ans);    }    return 0;}

太逗比了,刚刚又写了一遍,记得暑假的时候看这个题特别吃力

现在感觉好容易的一道题啊...明明是线段树练手题,这次写了一个bug。。。狂wa

代码如下:

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define MAXN 120010#define LL long longusing namespace std;int a[MAXN+10];LL c[MAXN+10], d[MAXN+10], x[MAXN+10];int lowbit(int x) {    return (-x)&x;}int sum(int k) {    int tmp = k;    LL ret = 0;    while(k > 0) {        ret += x[k];        k -= lowbit(k);    }    return ret;}void add(int k, int d) {    while(k <= MAXN) {       x[k] += d;        k += lowbit(k);    }}int main(void) {    int T, n;    scanf("%d", &T);    while(T--) {        scanf("%d", &n);        memset(x, 0, sizeof(x));        for(int i=1; i<=n; ++i) {            scanf("%d", &a[i]);            add(a[i], 1);            c[i] = sum(a[i])-1;            //printf("c[%d] = %d\n", i, c[i]);        }            memset(x, 0, sizeof(x));        for(int i=n; i>0; --i) {            add(a[i], 1);            d[i] = sum(a[i])-1;            //printf("d[%d] = %d\n", i, d[i]);        }        LL ans = 0ll;        for(int i=1; i<=n; ++i) {            ans += c[i]*(n-i-d[i])+(i-1-c[i])*d[i];        }        cout << ans << endl;    }    return 0;}


0 0
原创粉丝点击