BZOJ 2212 [Poi2011]Tree Rotations 線段樹合併
題目連結
題意
現在有一棵二叉樹,所有非葉子節點都有兩個孩子。在每個葉子節點上有一個權值(有
要求進行一系列交換,使得最終所有葉子節點的權值按照遍歷序寫出來,逆序對個數最少。
參考
Code
#include <bits/stdc++.h>
#define maxn 400010
using namespace std;
typedef long long LL;
LL ans, cnt1, cnt2;
int sum[maxn*10], ls[maxn*10], rs[maxn*10 ], root[maxn], v[maxn], sz, seg, l[maxn], r[maxn];
void read(int x) {
scanf("%d", &v[x]);
if (v[x]) return;
l[x] = ++sz;
read(l[x]);
r[x] = ++sz;
read(r[x]);
}
void push_up(int k) { sum[k] = sum[ls[k]] + sum[rs[k]]; }
void build(int& k, int l, int r, int val) {
if (!k) k = ++seg;
if (l == r) { ++sum[k]; return; }
int mid = l + r >> 1;
if (val <= mid) build(ls[k], l, mid, val);
else build(rs[k], mid+1, r, val);
push_up(k);
}
int merge(int x, int y) {
if (!x) return y;
if (!y) return x;
cnt1 += 1LL * sum[ls[x]] * sum[rs[y]];
cnt2 += 1L L * sum[rs[x]] * sum[ls[y]];
ls[x] = merge(ls[x], ls[y]);
rs[x] = merge(rs[x], rs[y]);
push_up(x);
return x;
}
void solve(int k) {
if (!k) return;
solve(l[k]), solve(r[k]);
if (root[k]) return;
cnt1 = cnt2 = 0;
root[k] = merge(root[l[k]], root[r[k]]);
ans += min(cnt1, cnt2);
}
void print(int x) {
if (!x) return;
printf("%d\n", x);
print(l[x]), print(r[x]);
}
int main() {
int n;
scanf("%d", &n);
read(++sz);
for (int i = 1; i <= sz; ++i) {
if (v[i]) build(root[i], 1, n, v[i]);
}
solve(1);
printf("%lld\n", ans);
return 0;
}
相關推薦
BZOJ 2212 [Poi2011]Tree Rotations 線段樹合併
題目連結 題意 現在有一棵二叉樹,所有非葉子節點都有兩個孩子。在每個葉子節點上有一個權值(有 n 個葉子節點,滿足這些權值為 1..n 的一個排列)。可以任意交換每個非葉子節點的左右孩子。 要
BZOJ 2212: [Poi2011]Tree Rotations 線段樹合併
Byteasar the gardener is growing a rare tree called Rotatus Informatikus. It has some interesting features: The tree consists of straight branches, bifurc
BZOJ 2212: [Poi2011]Tree Rotations(線段樹合並)
對數 long long ios php update mes 其余 etc name 傳送門 解題思路 線段樹合並,考慮交換兩個子樹時,對除這兩棵子樹外的其余點的逆序對不會造成影響,所以我們只需要貪心的使這兩棵子樹產生的逆序對最小。而考慮時我們也只需要考慮兩棵子樹間的
Luogu3521/BZOJ2212 POI2011 Tree rotations 線段樹合併
傳送門——Luogu 傳送門——BZOJ 葉子節點的權值兩兩不同,考慮線段樹合併進行統計。 首先有一個顯然的貪心策略:如果在某一個節點處,交換左右子樹會使得這一棵子樹內的逆序對個數更少,就一定要交換,因為現在交不交換對以後的狀態不會產生影響。 然後我們考慮如何計算交換或者不交換的逆序對數量。對於一
bzoj 2212 : [Poi2011]Tree Rotations (線段樹合並)
sin lse online space 量變 ++ ota hup 左右 題目鏈接:https://www.lydsy.com/JudgeOnline/problem.php?id=2212 思路:用線段樹合並求出交換左右兒子之前之後逆序對的數量,如果數量變小則交換.
BZOJ2212 [Poi2011]Tree Rotations 線段樹合並 逆序對
htm namespace 逆序 post php .html mat () targe 原文鏈接http://www.cnblogs.com/zhouzhendong/p/8079786.html 題目傳送門 - BZOJ3286 題意概括 給一棵n(1≤n≤20
BZOJ2212: [Poi2011]Tree Rotations(線段樹合並)
define getchar() dfs out fin c++ || 線段 影響 題意 題目鏈接 Sol 線段樹合並為什麽我會在這個時候學這種東西 就是暴力合並兩棵線段樹(必須動態開節點),遇到空節點就返回 可以證明,對於\(m\)個僅有一個元素,權值範圍在\([1, n
bzoj 1483: [HNOI2009]夢幻布丁 線段樹合併
題意很簡單,但是沒有資料範圍,這就是這題最難的地方 考慮線段樹合併。。 就是隨便搞搞 相信大家都會。。 就是這個資料範圍很坑爹。。。 經過我無限WA和RE 我得出了以下結論: 1.數字可以很大 2.n不超過10W 3.詢問非常非常多,比10W不
POI2011]ROT-Tree Rotations,洛谷P35231,線段樹合併
正題 給一顆n各節點的二叉樹,每個節點可以交換左右子樹,求先序遍歷的最小值。 這題很明顯,交換兩棵子樹,子樹內的逆序對不變的,變的只是左右兩邊出現的逆序對,那麼每一個葉子節點開一棵權值線段樹,每次向上合併
[BZOJ2212][Poi2011]Tree Rotations(線段樹合併)
Address 洛谷 P3521 BZOJ 2212 LOJ #2163 Solution 非常有意思的題 一個直觀的想法 對於一個點 u
【BZOJ2212】【POI2011】Tree Rotations(線段樹合併)
Description Solution 對於每個節點有一棵權值線段樹,向上遞迴時合併同時計算逆序對即可。 Source /*****************************
BZOJ2212 [Poi2011]Tree Rotations 【線段樹合並】
namespace 二叉 情況 一點 sizeof mem IV efi ota 題目鏈接 BZOJ2212 題解 一棵子樹內的順序不影響其與其它子樹合並時的答案,這一點與歸並排序的思想非常相似 所以我們只需單獨處理每個節點的兩棵子樹所產生的最少逆序對即可 只有兩種情況,要
BZOJ.3307.雨天的尾巴(dsu on tree/線段樹合併)
BZOJ 洛谷 \(dsu\ on\ tree\)。(線段樹合併的做法也挺顯然不寫了) 如果沒寫過\(dsu\)可以看這裡。 對修改操作做一下差分放到對應點上,就成了求每個點子樹內出現次數最多的顏色,這就和CF600E類似了。直接用\(dsu\)。 修改某個顏色出現次數的時候,最大值不能\(O(1)\)求
BZOJ 2212 [Poi 2011] 線段樹合併 解題報告
2212: [Poi2011]Tree Rotations Description 現在有一棵二叉樹,所有非葉子節點都有兩個孩子。在每個葉子節點上有一個權值(有n個葉子節點,滿足這些權值為1..n的
bzoj 2212(線段樹合併)
傳送門 題解:權值線段樹從下往上合併,每個點統計兩個兒子中某一個交換/不交換的答案,取min後加到總答案中。不禁讓人想起CDQZ Challenge 13 P.S.形態樹開兩倍空間,因為這種讀入方式
洛谷P3521 [POI2011]ROT-Tree Rotation [線段樹合並]
right its inline led open lse bits rotation any 題目傳送門 Tree Rotation 題目描述 Byteasar the gardener is growing a rare tree called Rotatus
BZOJ.5417.[NOI2018]你的名字(字尾自動機 線段樹合併)
LOJ 洛谷 BZOJ 考慮\(l=1,r=|S|\)的情況: 對\(S\)串建SAM,\(T\)在上面匹配,可以得到每個位置\(i\)的字尾的最長匹配長度\(mx[i]\)。 因為要去重,對\(T\)也建SAM,計算上面所有節點的答案。記\(pos[i]\)表示\(i\)節點第一次出現的下標(同一節點代表
bzoj 4756 [Usaco2017 Jan]Promotion Counting——線段樹合併
題目:https://www.lydsy.com/JudgeOnline/problem.php?id=4756 線段樹合併裸題。那種返回 int 的與傳引用的 merge 都能過。不知別的題是不是這樣。 #include<iostream> #include<cstdio>
BZOJ:5457: 城市(線段樹合併)(尚待優化)
5457: 城市 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 18 Solved: 12[Submit][Status][Discuss] Description 有n
線段樹合併 csu1811 Tree Intersection
題意:對於每條邊,把這條邊刪了,樹分成了兩個集合,求這兩個集合中共同的顏色數量。 對於節點u,就看u節點的子樹中,有多少種顏色沒有到達這種顏色的上限,就是對u所對應的邊的答案 方法一:我們用線段樹合併來維護,程式碼寫起來比較麻煩。 之所以可以用線段樹合併,是因為有一個結