LA 4329 - Ping pong 树状数组(Fenwick树)

先放看题传送门

哭瞎了,交上去一直 Runtime error 。以为那里错了。

狂改!!!!!

然后还是一直。。。

继续狂改!!!!。。。

一直。。。。

最后发现数组开小了。。。。。。。。。。

果断改了。。。。。AC了。。。。。。哭瞎了。。。。T T

笨蛋T T数组开太小这么愚蠢的错误也会犯!


笔记:

二叉索引树(也称Fenwick树)

对于节点i ,如果它是左子结点,父结点就是 i+ lowbit(i) 如果他是右结点, 父结点就是 i- lowbit(i)

C[]= A[ i -lowbit(i) +1] + A[ i -lowbit(i) +2]  +……A [i]




#include<cstdio>
#include<cstring>
#include<algorithm>
#include <iostream>
using namespace std;
const int MAXN=20000+10;
const int MAXA=100000+10;
int N;
int C[MAXA];               //这里存的是a必须大于a的最大值。一开始直接MAXN杯具
inline 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;
}

void add(int x,int d)
{
	while(x<=N)
	{
		C[x]+=d;
		x+=lowbit(x);
	}
}

int a[MAXN],c[MAXN],d[MAXN];
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		int n,m=0;
		scanf("%d",&n);
		for(int i=1;i<=n;i++)
		{
				scanf("%d",&a[i]);
				m=max(m,a[i]);
		}

		N=m;
		memset(C,0,sizeof(C));
		for(int i=1;i<=n;i++)
		{
			add(a[i],1);
			c[i]=sum(a[i]-1);
		}
		
		memset(C,0,sizeof(C));
		for(int i=n;i>=1;i--)
		{
			add(a[i],1);
			d[i]=sum(a[i]-1);
		}
		long long ans=0;
		for(int i=1;i<=n;i++)
			ans=ans+ (long long)c[i]*(n-i-d[i]) + (long long)(i-c[i]-1)*d[i];
		printf("%lld\n", ans);
	}
	return 0;
}


posted @ 2013-08-04 14:58  hr_whisper  阅读(161)  评论(0编辑  收藏  举报