求逆序对数。
线段树写法:
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
const int maxn=5500;
int x[maxn], sum[maxn<<2];
void pushup(int rt)
{
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void build(int l, int r, int rt)
{
sum[rt]=0;
if(l==r)return ;
int mid=(l+r)>>1;
build(lson);
build(rson);
}
void update(int p, int l, int r, int rt)
{
if(l==r)
{
sum[rt]++;
return ;
}
int mid=(l+r)>>1;
if(p<=mid)update(p, lson);
else update(p, rson);
pushup(rt);
}
int query(int L, int R, int l, int r, int rt)
{
if(L<=l && R>=r)
return sum[rt];
int mid=(l+r)>>1;
int ret=0;
if(L<=mid)ret+=query(L, R, lson);
if(R>mid)ret+=query(L, R, rson);
return ret;
}
int main()
{
int n;
while(~scanf("%d", &n))
{
build(0, n-1, 1);
int sum=0;
for(int i=0; i<n; i++)
{
scanf("%d", &x[i]);
sum+=query(x[i], n-1, 0, n-1, 1);
update(x[i], 0, n-1, 1);
}
int ans=sum;
for(int i=0; i<n; i++)
{
sum=sum-2*x[i]+n-1;
ans=min(ans, sum);
}
printf("%d\n", ans);
}
return 0;
}
树状数组写法:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=5500;
int bit[maxn], n, arr[maxn];
int lowbit(int x)
{
return x&-x;
}
void Add(int i, int c)
{
for(; i<=n; bit[i]+=c, i+=lowbit(i));
}
int Sum(int i)
{
int ans=0;
for(; i>0; ans+=bit[i], i-=lowbit(i));
return ans;
}
int main()
{
while(~scanf("%d", &n))
{
memset(bit, 0, sizeof(bit));
for(int i=0; i<n; i++)
scanf("%d", arr+i);
int sum=0;
for(int i=n-1; i>=0; i--)
{
sum+=Sum(arr[i]);
Add(arr[i]+1, 1);
}
int ret=sum;
for(int i=0; i<n; i++)
{
sum=sum+n-2*arr[i]-1;
ret=min(ret, sum);
}
printf("%d\n", ret);
}
return 0;
}