题目大意:给出一个序列, 要求求出这个序列和他经过环移后, 逆序数对中最小的一个。
思路;用线段树求逆序数, 每当加入一个数x时, 就求x~n-1有多少个数出现过, 出现多少就是多少逆序数对。
求出一组序列后, 环移后的逆序数对可以用公式求出, 环移用STL实现
code:
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define N 5002
using namespace std;
int t[4*N];
void update(int c, int l, int r, int w)
{
int m = l+(r-l)/2;
if(l == r)
{
t[c] = 1;
return ;
}
if(w<=m) update(2*c, l, m, w);
else update(2*c+1, m+1, r, w);
t[c] = t[2*c]+t[2*c+1];
}
int query(int c, int l, int r, int lf, int rt)
{
int sum = 0, m = l+(r-l)/2;
if(lf<=l && rt>=r)
return t[c];
if(lf<=m) sum += query(2*c, l, m, lf, rt);
if(rt>m) sum += query(2*c+1, m+1, r, lf, rt);
return sum;
}
int main()
{
int i = 0, n = 0, sum = 0, min = 0, num[N];
while(scanf("%d", &n) != EOF)
{
sum = 0;
memset(t, 0, sizeof(t));
for(i = 0; i<n; i++)
{
scanf("%d", &num[i]);
sum += query(1, 0, n-1, num[i], n-1);
update(1, 0, n-1, num[i]);
}
min = sum;
for(i = 0; i<n-1; i++)
{
sum = sum-num[0]+(n-1)-num[0];
rotate(num, num+1, num+n);
if(min>sum)
min = sum;
}
printf("%d\n", min);
}
return 0;
}