码迷,mamicode.com
首页 > 编程语言 > 详细

hdu 4000 Fruit Ninja(树状数组)

时间:2015-05-18 23:02:03      阅读:140      评论:0      收藏:0      [点我收藏+]

标签:

题目大意是给定一串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;	
}











hdu 4000 Fruit Ninja(树状数组)

标签:

原文地址:http://blog.csdn.net/u014664226/article/details/45827609

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!