題目:
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 及以下時間複雜度的演算法。逆序對的求解思路和歸併排序很像,嘗試...