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

HDU 4000 Fruit Ninja[树状数组]

2012-11-02 07:15 405 查看
题意:问一个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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: