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

hdu 4000 Fruit Ninja(树状数组)

2015-05-18 21:19 393 查看
题目大意是给定一串1到n的排列(设为数组a),求其中满足a[x]<a[z]<a[y]的排列个数,其中x<y<z

直接求这样的排列个数并不好求,我们可以转化为求a[x]<a[z]<a[y]+a[x]<a[y]<a[z]的个数减去a[x]<a[z]<a[y]的个数

用left数组记录i位置前比a[i]小的元素个数,left数组可由树状数组预处理得到,那么我们可以得到求排列个数的公式(具体见码)

#include<cstdio>  
#include<cstring>  
#include<cmath>  
#include<cstdlib>  
#include<iostream>  
#include<algorithm>  
#include<vector>  
#include<map>  
#include<queue>  
#include<stack> 
#include<string>
#include<map> 
#include<set>
using namespace std;  
#define LL long long 

const LL maxn = 100000 + 5;

LL C[2 * maxn], lef[maxn], n; //lef数组表示i之前比a[i]小的数的个数 

LL lowbit(LL x) {
	return x&(-x);
}

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

LL sum(LL x) {
	LL ret = 0;
	while(x > 0) {
		ret += C[x]; x -= lowbit(x);
	}
	return ret;
}

int main() {
	LL t, kase = 0; scanf("%I64d", &t);
	while(t--) {
		memset(C, 0, sizeof(C));
		scanf("%I64d", &n);
		
		LL ans = 0;
		for(LL i = 1; i <= n; i++) {
			LL tmp;
			scanf("%I64d", &tmp);
			lef[i] = sum(tmp);
			add(tmp, 1);
		//	prLLf("%I64d\n", lef[i]);
			ans = ans + (n + lef[i] + 1 - tmp - i) * (n  + lef[i] - tmp - i) / 2 - (n + lef[i] + 1 - tmp - i) * lef[i];
		}
		
		printf("Case #%I64d: %I64d\n", ++kase, ans % 100000007);
	}
	return 0;	
}



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: