hdu 4000 Fruit Ninja 树状数组+统计

/*
比赛的时候没有写出来,赛后请教大牛后写的
可以先求出(xyz,xzy)的总数量
只需出去x后面多少个比它大的个数n,C(n,2)就是了
然后求出xyz的个数,
对于a,求出比a小的个数low[a],比a大的个数high[a],low[a]*high[a]就是答案
可以借助树状数组求上述个数
*/
#include <cstdio>
#include <iostream>
#include <memory.h>
using namespace std;

const int MAX=100100;
const __int64 mod=100000007;

__int64 C[MAX];
__int64 low[MAX];//low[a],在a前面比a小的个数
__int64  high[MAX];//high[a],在a后面比a大的个数
int Case;
int n;
int data[MAX];

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

void add_up(int x) {
	while(x<=n) {
		C[x]+=1;
		x+=low_bit(x);
	}
}

__int64 sum(int x) {
	__int64 s=0;
	while(x) {
		s+=C[x];
		x-=low_bit(x);
	}
	return s;
}

void solve() {
	Case++;
	__int64 a=0, b=0;
	scanf("%d", &n);
	memset(C, 0, sizeof(C));
	for(int i=1;i<=n;i++) {
		scanf("%d", &data[i]);
		low[i]=sum(data[i]);
		high[i]=n-data[i]-i+1+low[i];
		add_up(data[i]);
	}
	for(int i=1;i<=n;i++) {
		b=((b+low[i]*high[i])%mod+mod)%mod;
	}
	for(int i=1;i<=n;i++) {
		a=((a+high[i]*(high[i]-1)/2)%mod+mod)%mod;
	}
	printf("Case #%d: ", Case);
	printf("%I64d\n", (a-b+mod)%mod);
}

int main () {
	int T;
	scanf("%d", &T);
	while(T--)
		solve();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值