逆序對 (沒看懂)

2021-07-29 13:38:24 字數 1744 閱讀 2820

題目:

alice是乙個讓人非常愉躍的人!他總是去學習一些他不懂的問題,然後再想出許多稀奇古怪的題目。這幾天,alice又沉浸在逆序對的快樂當中,他已近學會了如何求逆序對對數,動態維護逆序對對數等等題目,他認為把這些題讓你做簡直是太沒追求了,於是,經過一天的思考和完善,alice終於拿出了一道他認為差不多的題目:

有一顆2n-1個節點的二叉樹,它有恰好n個葉子節點,每個節點上寫了乙個整數。如果將這棵樹的所有葉子節點上的數從左到右寫下來,便得到乙個序列a[1]…a[n]。現在想讓這個序列中的逆序對數量最少,但唯一的操作就是選樹上乙個非葉子節點,將它的左右兩顆子樹交換。他可以做任意多次這個操作。求在最優方案下,該序列的逆序對數最少有多少。

alice自己已近想出了題目的正解,他打算拿來和你分享,他要求你在最短的時間內完成。

輸入格式

第一行乙個整數n。

下面每行,乙個數x。

如果x=0,表示這個節點非葉子節點,遞迴地向下讀入其左孩子和右孩子的資訊,如果x≠0,表示這個節點是葉子節點,權值為x。

輸出格式

輸出乙個整數,表示最少有多少逆序對。

樣例輸入3

0 0

3 1

2 樣例輸出

1 參考**:

#include#includeusing namespace std;

#define ford(i,n) for(int i = n;i ;i --)

#define f (100000007)

#define maxn (2*200000 + 10)

long long mul(long long a,long long b)

long long add(long long a,long long b)

long long sub(long long a,long long b)

int n,root = 0;

struct node

}a[maxn];

int tail = 0;

int q[maxn],size;

void update(int x)

void pushdown(int x)

void build(int &x)

else a[x].size = 1;

// cout << "##" << x<< endl;我以為是先序遍歷,但輸出x的結果是 ###3\n,###4\n,###2\n,###5\n,###1\n

}void rotate(int x)

a[x].fa = z,a[y].fa = x;

if(a[x].ch[p]) a[a[x].ch[p]].fa = y;

a[y].ch[p^1] = a[x].ch[p];

a[x].ch[p] = y;

update(y);

}void splay(int x)

update(x);

}void ins(long long &tot,int x,int y)

else }

void clac(int x,int y)

long long merge(bool &lor,int z)

a[x].fa = z;

a[z].ch[0] = 0,a[z].ch[1] = x;

return tot;

}long long qur(int &x) }

int main()

求逆序對,一般採用歸併排序:

鍊錶 翻轉鍊錶 還沒看懂

題目 定義乙個函式,輸入乙個鍊錶的頭節點,反轉該鍊錶並輸出反轉後鍊錶的頭節點。示例 輸入 1 2 3 4 5 null 輸出 5 4 3 2 1 null 限制 0 節點個數 5000 思路 思路一 利用外部空間 新建乙個列表,遍歷鍊錶的同時將鍊錶儲存到列表中 然後使用pop將鍊錶從後往前彈出,然後...

尋找逆序對

設a 1.n 是乙個包含n個不同數的陣列。如果在ia j 則 i,j 就成為a中的乙個逆序對 inversion 要確定乙個陣列中的逆序對的個數,可以採取分治法。將a分為兩部分a1和a2,則a中逆序對的數目等於a1中逆序對的數目 a2中逆序對的數目和a1,a2合併時a1中比a2中元素大的數目。inc...

逆序對問題

逆序對問題。給一列數a1 a2,an 求它的逆序對數,即有多少個有序對 i j 使得 i j 但ai aj n 可以高達106 由於 n 的數量級到了106 所以採用o n2 及以上的時間複雜度肯定會超時,所以必須選取o nlog 2n 及以下時間複雜度的演算法。逆序對的求解思路和歸併排序很像,嘗試...