![]() Rating:978 | A和D都是水题,就不说了 B题。。。假定l[i]表示数组中在a[i]前面且比a[i]小的数的个数,r[i]表示在数组中在a[i]后面且比a[i]大的数的个数,那么答案就可以计算了,用i和j表示Ab和Ac的位置,则这种情况的个数等于l[i]*r[j]。然后用前缀和优化该式子可以达到O(N)。求l和r数组用树状数组或线段树,复杂度O(n*logn)。 E题。。。可以知道总情况个数是a^b,这么多情况中,没出现数字i的情况数是(a-1)^b,其他情况出现过i,可能多次但是只计算一次。所以总和就等于a^b-(a-1)^b*( 1..n的和 ) 。 以下内容于[2015-07-20 22:26:14]补充 #include<stdio.h>
#include<algorithm>
using namespace std;
#define MAXLEN 50001
int c[MAXLEN],n;
int A[50005];
int Lowbit(int x)//1<<k (k表示x在二进制下末尾0的个数)
{
return x&(-x);
}
/*查询1~end的和*/
int sum(int end)
{
int sum=0;
while(end>0)
{
sum+=c[end];
end-=Lowbit(end);
}
return sum;
}
/*将a[pos]的值加上num*/
void update(int pos,int num)
{
while(pos<=n)
{
c[pos]+=num;
pos+=Lowbit(pos);
}
}
int l[50005];
int r[50005];
int main(){
int t;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&A[i]);
c[i]=0;
}
for(int i=0;i<n;i++){
update(A[i],1);
l[i]=sum(A[i]-1);
}
for(int i=0;i<n;i++){c[i]=0;}
for(int i=n-1;i>=0;i--){
update(A[i],1);
r[i]=n-i-sum(A[i]-1)-1;
}
int sum=0;
long long ans=0;
for(int i=0;i<n;i++){
ans+=(long long)r[i]*sum;
//printf("%d %d %d*%d\n",l[i],r[i],r[i],sum);
sum+=l[i];
}
printf("%lld\n",ans);
}
return 0;
}
|