题目描述:
学习了y神的讲解,但是对树状数组还不理解,写下博客为了方便后面学习,下面代码为Acwing题解里Jackle的代码。
一、暴力枚举O(n*n)
#include<bits/stdc++.h>
using namespace std;
const int N=1100;
int a[N],b[N];
int main()
{
//求逆序数
int n;
cin>>n;
int res=0;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++)
{
for(int j=1;j<i;j++)
{
if(a[j]>a[i])b[a[i]]++;
}
res+=b[a[i]];
}
for(int i=1;i<=n;i++)cout<<b[i]<<' ';
printf("\n%d",res);
return 0;
}
二、树状数组O(n*logn)
#include<bits/stdc++.h>
using namespace std;
const int N=1100;
int c[N],b[N],n;
int lowbit(int x)
{
return x&-x;
}
void add(int x,int k)
{
for(int i=x;i<=n;i+=lowbit(i))c[i]+=k;
}
int ask(int x)
{
int sum=0;
for(int i=x;i;i-=lowbit(i))sum+=c[i];
return sum;
}
int main()
{
cin>>n;
int res=0;
for(int i=1;i<=n;i++)
{
int x;
cin>>x;
b[x]+=ask(n)-ask(x-1);
res+=b[x];
add(x,1);
}
for(int i=1;i<=n;i++)cout<<b[i]<<' ';
cout<<'\n'<<res<<endl;
return 0;
}
归并排序为先查找l到mid的逆序对并排序,再查找mid+1到r的逆序对排序,算法内是双指针进行操作。
三、归并排序O(n*logn)
#include<bits/stdc++.h>
using namespace std;
const int N=1100;
int a[N],b[N],tmp[N],n;
int get(int l,int r)
{
if(l>=r)return 0;
int mid=l+r>>1;
int sum=get(l,mid)+get(mid+1,r);
int k=0,i=l,j=mid+1;
while(i<=mid&&j<=r)
{
if(a[i]<=a[j])tmp[k++]=a[i++];
else
{
b[a[j]]+=mid-i+1;
sum+=mid-i+1;
tmp[k++]=a[j++];
}
}
while(i<=mid)tmp[k++]=a[i++];
while(j<=r)tmp[k++]=a[j++];
for(int i=l,j=0;i<=r;i++,j++)a[i]=tmp[j];
return sum;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
int res=get(1,n);
for(int i=1;i<=n;i++)cout<<b[i]<<' ';
cout<<'\n'<<res<<endl;
return 0;
}