白书上树状数组例题,感觉看起来太吃力了
设输入为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 long
int 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 long
using 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;
}
这篇博客讲述了作者在解决POJ 3928问题时,如何运用树状数组(也称线段树)解决关于数据结构的难题。作者回顾了自己初次接触该问题时的困扰,以及现在对该问题的理解和解决方案,尽管在实现过程中遇到了一些错误。代码实现被提及,但未给出详细内容。
2787

被折叠的 条评论
为什么被折叠?



