您的位置:首页 > 产品设计 > UI/UE

hdu 5147 Sequence II

2016-10-21 19:18 351 查看
hdu 5147 Sequence II 树状数组

参考 http://blog.csdn.net/ljd4305/article/details/10101535

http://www.cnblogs.com/zhj5chengfeng/archive/2013/03/20/2965833.html

遇到了这道题不会,看了题解现学的树状数组= =望轻喷

假设A[]数组为存储原来的值得数组,C[]为树状数组。

首先先看一下树状数组的基本操作:

Ⅰ:一个数组 tree[idx] 记录的是

令 k 表示:在 idx 的二进制表示下,最后一个 1 的位置

那么 tree[idx] 表示:下标 i 在 [idx-2^k+1, idx]区间 中的 a[i] 的和

int lowbit(int x){
return x&(-x);   //利用补码求得k
}


Ⅱ:下面我们还要求的就是如何快速的修改某一个元素的值以及求出某一段元素值的和;(具体实现可以参考链接)时间复杂度O(logn)

//假设现在要更新的是 x,能影响到的下一个是 x+(x&(-x))
void update(int tree[], int pos, int val)
{
for(; pos<N; pos+=pos&(-pos))
tree[pos]+=val;
}


//查询某段区间的和
int query(int tree[], int pos)
{
int sum=0;
for(; pos; pos-=pos&(-pos))
sum+=tree[pos];
return sum;
}


//查询某个点的值
query(tree, pos)-query(tree, pos-1)


AC代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#define maxn 50050
#define me(a) memset(a,0,sizeof(a))
typedef long long ll;
using namespace std;

int a[maxn], tree[maxn], n;
ll pre[maxn], tail[maxn];

int get_k(int x)
{
return x&(-x);
}

void add(int x, int y)
{
for (int i = x; i <= n; i += get_k(i))
tree[i] += y;
}

int sum(int x)
{
int s = 0;
for (int i = x; i; i -= get_k(i))
s += tree[i];
return s;
}

int main()
{
int t;
scanf("%d", &t);
while (t--)
{
scanf("%d", &n);
me(tree);
for (int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
pre[i] = sum(a[i]);
add(a[i], 1);
}
me(tree);
for (int i = n; i > 0; i--)
{
tail[i] = n - i - sum(a[i]);
add(a[i], 1);
}
for (int i = n - 1; i > 0; i--)
tail[i] += tail[i + 1];
ll ans = 0;
for (int i = 1; i < n; i++)
ans += pre[i] * tail[i + 1];
printf("%lld\n", ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: