本文主要是介绍HDU 4000 Fruit Ninja,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
参看资料:
https://blog.csdn.net/keepcoral/article/details/80550168
题目:
Recently, dobby is addicted in the Fruit Ninja. As you know, dobby is a free elf, so unlike other elves, he could do whatever he wants.But the hands of the elves are somehow strange, so when he cuts the fruit, he can only make specific move of his hands. Moreover, he can only start his hand in point A, and then move to point B,then move to point C,and he must make sure that point A is the lowest, point B is the highest, and point C is in the middle. Another elf, Kreacher, is not interested in cutting fruits, but he is very interested in numbers.Now, he wonders, give you a permutation of 1 to N, how many triples that makes such a relationship can you find ? That is , how many (x,y,z) can you find such that x < z < y ?
Input
The first line contains a positive integer T(T <= 10), indicates the number of test cases.For each test case, the first line of input is a positive integer N(N <= 100,000), and the second line is a permutation of 1 to N.
Output
For each test case, ouput the number of triples as the sample below, you just need to output the result mod 100000007.
Sample Input
2 6 1 3 2 6 5 4 5 3 5 2 4 1Sample Output
Case #1: 10 Case #2: 1
题目大意:
给定 N 个数的数组A,问能够找到多少(x,y,z),使得 x< y< z,且 A[ x ]<A[ z ]<A[ y ] 。
解题思路:
要以整体【整个数组】的思想来看这道题,就会明白这个人到底在做什么。
当我们输入第 i 个数字 a 时,用的树状数组存储 sum(a-1) 【sum(a-1) 表示:在a这个位置的前 i-1 个数中,有sum(a-1)个数比 a 小】。
那么,就可以求出在 a 后面的 (i+1,n) 的序列中,有 R=(n-a)-(i-1-sum(a-1)) 个数比a要大【(n-a)表示有这么多个数比a大,(i-1-sum(a-1))表示前i-1个数里面有sum(a-1)个数比a大】。
然后,让a当作三个数里面的最小值,以此取出三个数的组合,就有 C(R,2) 即 R*(R-1)/2 ,因为后面的序列都是固定的,所以并没有排序的概念。【例:原本序列1 5 4 ,那么我们没有必要去思考1 4 5的情况,因为它已经固定好了(一开始死都想不通....)】。
所以后面的序列选的时候直接从R个选2个就可以了,然后C(R,2)表示所有的a与两个大于 a 的数的组合【也就是小中大,小大中都包含在里面了】。那么我们要求的是小大中,所以对于每一个a来说,我们都需要减去 “小中大” 的情况,那么小中大=sum(a-1)*R,所以最后答案就是对于(1,n)所有数,求和SUM(C(R,2)-sum(a-1)*R)
实现代码:
#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
int n;
ll c[100009];
ll lowbit(ll x){return x&(-x);
}
ll getsum(ll x){ll sum=0;while(x){sum+=c[x];x-=lowbit(x);}return sum;
}
void update(ll x,ll val){while(x<=n){c[x]+=val;x+=lowbit(x);}
}
int main(){int i,T;scanf("%d",&T);int Count=1;while(T--){ll ans=0;scanf("%d",&n);memset(c,0,sizeof(c));for(i=1; i<=n; i++){ll a,L,R;scanf("%lld",&a);update(a,1);L=getsum(a-1); //Left表示有多少个数比a小,R=(n-a)-(i-1-L);//前面n-a的含义是有多少个数比a大//(i-1-Left)表示i-1个数里面有这么多个数比a大ans+=R*(R-1)/2-L*R;}printf("Case #%d: %lld\n",Count++,ans%100000007);}
}
这篇关于HDU 4000 Fruit Ninja的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!