/*Binary indexed Tree
给定初始值全为0的数列 A1,A2,A3……An
1:给定i 求A1+A2+……+Ai
2:给定i和 X求Ai+= X;
*/
# include<stdio.h>
# define N 101
int SUM(int BIT[],int i)
{
int sum=0;
if(i>BIT[0]) i=BIT[0];
while(i>0){
sum+=BIT[i];
i&=i-1;
}
return sum;
}
void ADD(int BIT[],int i,int x)
{
while(i<=BIT[0]){
BIT[i]+=x;
i+=i&-i;
}
}
int main(){
int A[N]={0},i,t,j;
freopen("haha.txt","r",stdin);
scanf("%d ",&A[0]);
for(i=1;i<=A[0];i++)
{
scanf("%d",&t);
ADD(A,i,t);
for(j=1;j<=A[0];j++)
printf("%4d ",A[j]);
printf("\n");
}
for(i=1;i<=15;i++)
printf("%d\n",SUM(A,i));
return 0;
}
/*Binary indexed Tree
给定初始值全为0的数列 A1,A2,A3……An
1:给定i 求A1+A2+……+Ai
2:给定i和 X求Ai+= X;
给定N个元素的{Ai}数组,求对这N个元素进行冒泡排序的所需的交换次数 N∈[1,100000]
冒泡排序是 一种 每次找到满足的Ai>Ai+1的i,并交换Ai和Ai+1 知道最后不存在这样的i的算法
EG:输入N=4 A={3,1,4,2};
输出 :3
解:
冒泡排序的复杂度为0(N^2) 显然不行 BIT 树状数组
逆序数:
i<j but AI>Aj的数对的个数
对于每一个j 如果能快速求出满足次条件的逆序数的i的个数,那么问题就迎刃而解
我们做如下操作:把j-(BIT[]查询所得到的前Aj的和加到答案中)
把BIT的A[j]++
对于每一个j,BIT[]查询所得到的Aj的前Aj项的和就是满足i<j ai<=aj的个数
j再减去这个数 就是逆序数的个数
对每一个J的操作都是0(logN)所以整个算法的复杂度0(NlogN);
*/
# include<stdio.h>
# define N 101
int A[N];
int SUM(int BIT[],int i) //求前i项和
{
int sum=0;
if(i>BIT[0]) i=BIT[0]; //为了防止形参错误导致数组越界
while(i>0){
sum+=BIT[i]; //求SUM
i&=i-1; //移动i
}
return sum;
}
void ADD(int BIT[],int i,int x) //把第i项改为BIT[i]+=x
{
while(i&&i<=BIT[0]){
BIT[i]+=x;
i+=i&-i;
}
}
int main(){
long long sum=0;
int i,t;
//freopen("SSS.txt","r",stdin);
scanf("%d ",&A[0]);
for(i=1;i<=A[0];i++)
scanf("%d",&A[i]);
for(i=1;i<=A[0];i++)
{
sum+=i+1-SUM(A,A[i]+1);
ADD(A,A[i]+1,1);
}
printf("%lld\n",sum);
return 0;
}