HDU 1394 - Minimum Inversion Number(线段树)

    xiaoxiao2021-12-15  34

    Minimum Inversion Number

    Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 18913 Accepted Submission(s): 11420

    Problem Description The inversion number of a given number sequence a1, a2, …, an is the number of pairs (ai, aj) that satisfy i < j and ai > aj.

    For a given sequence of numbers a1, a2, …, an, if we move the first m >= 0 numbers to the end of the seqence, we will obtain another sequence. There are totally n such sequences as the following:

    a1, a2, …, an-1, an (where m = 0 - the initial seqence) a2, a3, …, an, a1 (where m = 1) a3, a4, …, an, a1, a2 (where m = 2) … an, a1, a2, …, an-1 (where m = n-1)

    You are asked to write a program to find the minimum inversion number out of the above sequences.

    Input The input consists of a number of test cases. Each case consists of two lines: the first line contains a positive integer n (n <= 5000); the next line contains a permutation of the n integers from 0 to n-1.

    Output For each case, output the minimum inversion number on a single line.

    Sample Input 10 1 3 6 9 0 8 5 7 4 2

    Sample Output 16

    题意: 给出n个数,n次操作,每次都把第一个元素放到最后。 问形成的n个数组中的最小逆序数。

    解题思路: 如果已知某一数组的逆序数,那么把第i个元素放到最后,新数组的逆序数为 sum + n - 1 - a[i]*2

    那么现在是求对于每一个插入的数,已有的比他大的数的个数。 就用线段树去搜索,节点记录下区间里的数出现的总次数。

    AC代码:

    #include<bits/stdc++.h> #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 using namespace std; const int maxn = 5e3; int stree[maxn<<1]; int a[maxn]; void PushUp(int rt) {stree[rt] = stree[rt<<1]+stree[rt<<1|1];} void build(int l,int r,int rt) { stree[rt] = 0; if(l == r) return ; int mid = (l+r)>>1; build(lson); build(rson); } int query(int L,int R,int l,int r,int rt) { if(L <= l && R >= r) return stree[rt]; int mid = (l+r)>>1; int res = 0; if(L <= mid) res += query(L,R,lson); if(R > mid) res += query(L,R,rson); return res; } void Update(int l,int r,int rt,int c) { if(l == r) { stree[rt]++; return ; } int mid = (l+r)>>1; if(c <= mid) Update(lson,c); else Update(rson,c); PushUp(rt); } int main() { int n; while(~scanf("%d",&n)) { build(1,n,1); int sum = 0; for(int i = 0;i < n;i++) { scanf("%d",&a[i]); sum += query(a[i]+1,n-1,0,n-1,1); Update(0,n-1,1,a[i]); } int res = INT_MAX; for(int i = 0;i < n;i++) sum += n-1-a[i]*2, res = min(res,sum); printf("%d\n",res); } return 0; }
    转载请注明原文地址: https://ju.6miu.com/read-999982.html

    最新回复(0)