1. 程式人生 > >hdu Minimum Inversion Number(線段樹求逆序數有關問題的一個小歸納)

hdu Minimum Inversion Number(線段樹求逆序數有關問題的一個小歸納)

Minimum Inversion Number

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


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
Author CHEN, Gaoli
Source
Recommend Ignatius.L 首先,求逆序數對的思路: 1.得到整個數列後,從前往後掃,統計比a[i]小的,在a[i]後面的有多少個 這樣做的話,應該是隻有n2的暴力作法,沒想到更好的方法 2.統計a[i]前面的,且比它大的數 這樣做的話,就可以利用輸入的時效性,每輸入一個數,就把這個數的num[i]值加1, 然後統計比這個數大的數的num和, 因為這裡的和一定是在這個數列中比a[i]大,且在它前面出現的數之和, 然後把把這個和加到總逆序數sum裡。 這樣做的話直接的暴力作法依然是n2,但是, 我們可以在,統計
比這個數大的數的num和這一步進行優化,利用線段樹求區間域值的複雜度是logn, 所以總體複雜度就降到了nlogn。 再來看這道題,求得初始數列的逆序數後,再求其他排列的逆序數有一個規律,就是 sum = sum + (n - 1 - a[i]) - a[i]; 這個自行驗證吧,相信很容易得出 最後,拓展一下,如果要求正序數怎麼辦?很簡單,無非是大小調一下 再問,如果要求滿足i<j<k,且a[i]>a[j]>a[k]的數對總數怎麼辦? 可以從中間的這個數入手,統計a[i]>a[j]的對數m,以及a[j]>a[k]的對數n,m*n就是。。。 要求a[i]>a[j]的個數還是一樣的,那麼a[j]>a[k]的個數呢? 兩種思路: 1.得到a[i]>a[j]的對數後,將數列倒過來後再求a[j]<a[k]的對數 2.更簡單的做法是,找到規律發現,n = 整個數列中比a[j]小的數 — 在a[j]前面已經出現的比a[j]小的數的個數 即(假設數列是從1開始的) n = (a[j] -1) - (j - 1 - m ) 這道題程式碼
#include <stdio.h>
#include <algorithm>

using namespace std;

int a[5005];
struct Node{
    int l,r,num;
}tree[50000];

void Build(int n,int x,int y){
    tree[n].l = x;
    tree[n].r = y;
    tree[n].num = 0;
    if(x == y){
        return;
    }
    int mid = (x + y) / 2;
    Build(2*n,x,mid);
    Build(2*n+1,mid+1,y);
}

void Modify(int n,int x){
    int l = tree[n].l;
    int r = tree[n].r;
    int mid = (l + r) / 2;
    if(x == l && x == r){
        tree[n].num = 1;
        return;
    }
    if(x <= mid)    Modify(2*n,x);
    else            Modify(2*n+1,x);
    tree[n].num = tree[2*n].num + tree[2*n+1].num;
}

int Query(int n,int x,int y){
    int l = tree[n].l;
    int r = tree[n].r;
    int mid = (l + r) / 2;
    int ans = 0;;
    if(x == l && y == r)
        return tree[n].num;
    if(x <= mid)   ans += Query(2*n,x,min(mid,y));
    if(y > mid)    ans += Query(2*n+1,max(mid+1,x),y);
    return ans;
}
int main(){
    int n,sum,ans;
    int i,j;

    while(scanf("%d",&n) != EOF){
        sum = 0;
        Build(1,0,n);
        for(i = 1;i <= n;i++){
            scanf("%d",&a[i]);
            Modify(1,a[i]);
            sum += Query(1,a[i]+1,n);
        }
        ans = sum;
        for(i = 1;i < n;i++){
            sum = sum + (n - 1 - a[i]) - a[i];
            if(sum < ans)
                ans = sum;
        }
        printf("%d\n",ans);
    }
}


相關推薦

hdu Minimum Inversion Number線段序數有關問題的一個歸納

Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 4904  

hdu1394 Minimum Inversion Number 線段序數&&思維

題目傳送門 Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s)

Minimum Inversion Number 線段解決序數問題

Minimum Inversion Number 線段樹解決逆序數問題 The inversion number of a given number sequence a1, a2, …, an is the number of pairs (ai, aj) t

poj3264線段區間最大最

簡單題,求區間最大值和最小值 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 1000010 int n,a[N

HDU】1394Minimum Inversion Number-線段單點更新,序數

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 25122 &n

CodeForces - 1093G:Multidimensional Queries 線段K維最遠點距離

題意:給定N個K維的點,Q次操作,或者修改點的座標;或者問[L,R]這些點中最遠的點。 思路:因為最後一定可以表示維+/-(x1-x2)+/-(y1-y2)+/-(z1-z2)..... 所以我們可以儲存到線段樹裡,每次求區間最大值和最小值即可。 注意到我們可以先確定一個點的正負號,所以時間和空間節省了

hdu 6273 Master of GCD線段區間維護兩個最

Hakase has n numbers in a line. At first, they are all equal to 1. Besides, Hakase is interested inprimes. She will choose a continuous su

hdu 1394(線段序數)

題意描述:給你一個有0--n-1數字組成的序列,然後進行這樣的操作,每次將最前面一個元素放到最後面去會得到一個序列,那麼這樣就形成了n個序列,那麼每個序列都有一個逆序數,找出其中最小的一個輸出! 分析:其實只需求出一個序列的逆序數即可,一位第i+1個序列的逆序數為第i

Ultra-QuickSort (線段序數+離散化)

+= build https sse nbsp != ble ultra for Ultra-QuickSort OpenJ_Bailian - 2299 In this problem, you have to analyze a particular sorting

POJ 2299 Ultra-QuickSort 線段+序數+離散化

In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swapping

hdu 1694 Minimum Inversion Number 狀陣列

題目連結:哆啦A夢傳送門 題意:給你一串n個值,每個a[i] 範圍在 [ 0 , n-1 ] ,然後我們可以把序列的頭部移到尾部,這樣就有n中不同的序列,問:在這n條序列中逆序數最少的是多少? 題解:我們可以用樹狀陣列,具體看程式碼註釋。 樹狀陣列模板:樹狀陣列 #inclu

Minimum Inversion Number 單點更新 線段

Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 19112 

hdu-1255線段面積並模板

題目連結:傳送門 思路: (1)建立線段的資訊,每個線段儲存l到r的線段的x位置和y的起始點與終點。 建立線段樹的節點資訊,每個節點代表一個區間的資訊,x表示區間的橫座標的位置,l,r表示縱座標的範圍,flag表示是否標記過,cover表示線段的覆蓋次數。 (2)先將y的位置按照從小到大排序,再將邊按

1394.Minimum Inversion NumberHDU

題意理解 給定一個長度N的全排列,對這樣的一個序列對應一個逆序數;現在每次將第一個數放到序列最後一位,形成一個新的序列,這個新序列也對應一個逆序數。求所有這些放法對應逆序數的最小值。逆序數定義:對於i<j,a[i]>a[j]。 問題分析 用樹狀陣列資料結構 轉一:問題分兩

hdu 2665 Kth number劃分

first con build 這一 cst second class stream tom Kth number Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Oth

HDU 4553 約會安排線段區間合並+雙重標記

stack 基本 pushd 一段 ret problem 代碼 () vector 題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=4553 題目大意:就是有三種操作:      ①DS x,安排一段長度為x的空閑時間跟屌

HDU 1540 Tunnel Warfare線段 區間合並

tle def ons main logs tmp 區間合並 http 合並 題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=1540 題意:n個村子,相鄰兩個村子初始都是聯通的,詢問經過一些操作後村子x最多和幾個村子聯通(包

hdu 5919--Sequence II主席--區間不同數個數+區間第k大

positions minus -s ima date rst itl 主席樹 技術 題目鏈接 Problem Description Mr. Frog has an integer sequence of length n, which can be denot

hdu 6183 Color it 線段 動態開點

appears sub TP data- PE class pri operation count Do you like painting? Little D doesn‘t like painting, especially messy color paintings.

HDU 1540 Tunnel Warfare線段

題意:一條線上的點,D x是破壞這個點,Q x是表示查詢以x所在的最長的連續的點的個數,R是恢復上一次破壞的點。 分析:還是最大連續區間的板題,不過就是變成了單個節點進行更新。直接套用板子稍微更改就好, #include<cstdio> #include<cstring&g