HDU 4000 Fruit Ninja[树状数组]
题意:问一个1..n 的排列中,有多少组数满足 i < j < k 且 num[i] < num[k] < num[j].
分析:符合条件的答案即为 小大中的情况总数,而
小大中 = 小XX - 小中大
可以求出每个数前面小于它的数的个数x,和后面大于它的个数y,
那么每个数对应的 小XX 数量为 y*(y-1)/2
每个数对应的 小大中数量为 x*y
#include <stdio.h> #include <string.h> #define mod 100000007 long long a[100005]; int n; int lowbit(int x) { return (x)&(-x); } void add(int pos) { while (pos <= n) { a[pos] += 1; pos += lowbit(pos); } } long long sum(int pos) { long long s = 0; while (pos > 0) { s += a[pos]; pos -= lowbit(pos); } return s; } int main() { int ca = 1; int t, i, j; int p; long long t1, t2, t3, s1, s2; scanf("%d",&t); while (t--) { scanf("%d",&n); s1 = s2 = 0; for(i=0; i<=n; i++) a[i] = 0; for(i=1; i<=n; i++) { scanf("%d",&p); add(p); t1 = sum(p-1); t2 = sum(n) - sum(p); t3 = n - p - t2; s2 += ((t1%mod)*(t3%mod))%mod; if (t3%2 == 0) s1 += (((t3/2)%mod)*((t3-1)%mod))%mod; else s1 += ((((t3-1)/2)%mod)*(t3%mod))%mod; s1 %= mod; s2 %= mod; } int res = (s1 - s2 + mod)%mod; printf("Case #%d: %d\n",ca++,res); } return 0; }