hdu 1394
题意:给出一个0到n-1的排列, 求题目所给的所有形式的最小逆序数
1 暴力
#include <cstdio>
#include <algorithm>
using namespace std;
int a[5010], n;
int main()
{
while(scanf("%d", &n) == 1)
{
int ans1, ans = 0;
for(int i=1; i<=n; i++)
scanf("%d", &a[i]);
for(int i=1; i<=n-1; i++)
for(int j=i+1; j<=n; j++)
if(a[i] > a[j])
ans++;
ans1 = ans;
for(int i=1; i<=n-1; i++)
{
int count = 0;
for(int j=2; j<=n; j++)
if(a[1] > a[j])
count++;
ans1 = ans1-count+n-1-count;
ans = min(ans, ans1);
int t = a[1];
for(int j=2; j<=n; j++)
a[j-1] = a[j];
a[n] = t;
}
printf("%d\n", ans);
}
return 0;
}
2 线段树
node[0]表示节点对应区间的已插入数字个数, 当输入X时, 需求x到n的已插入个数
#include <cstdio>
#include <algorithm>
using namespace std;
int node[5010*4], a[5010], n, x;
void construct(int o, int l, int r)
{
node[o] = 0;
if(l != r)
{
int m = (l+r) / 2;
construct(2*o, l, m);
construct(2*o+1, m+1, r);
}
}
void update(int o, int l ,int r)
{
if(l == r)
node[o] = 1;
else
{
int m = (l+r) / 2;
if(x <= m)
update(2*o, l, m);
else
update(2*o+1, m+1, r);
node[o] = node[2*o] + node[2*o+1];
}
}
int query(int o, int l, int r)
{
if(l>=x+1)
return node[o];
if(r < x+1)
return 0;
int m = (l+r) / 2;
return query(2*o, l, m) + query(2*o+1, m+1, r);
}
int main()
{
while(scanf("%d", &n) == 1)
{
construct(1, 1, n);
int ans, count1, count2;
ans = 0;
for(int i=1; i<=n; i++)
{
scanf("%d", &x);
x++;
a[i] = x;
update(1, 1, n);
ans += query(1, 1, n);
}
count1 = ans;
for(int i=1; i<n; i++)
{
count2 = 0;
for(int j=2; j<=n; j++)
if(a[1] > a[j])
count2++;
count1 = count1-count2+n-1-count2;
ans = min(ans, count1);
int t = a[1];
for(int j=2; j<=n; j++)
a[j-1] = a[j];
a[n] = t;
}
printf("%d\n", ans);
}
return 0;
}