bzoj3702 二叉樹 線段樹

2021-07-12 02:44:53 字數 1075 閱讀 5583

現在有一棵二叉樹,所有非葉子節點都有兩個孩子。在每個葉子節點上有乙個權值(有n個葉子節點,滿足這些權值為1..n的乙個排列)。可以任意交換每個非葉子節點的左右孩子。

要求進行一系列交換,使得最終所有葉子節點的權值按照中序遍歷寫出來,逆序對個數最少。

第一行n

下面每行,乙個數x

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

如果x!=0,表示這個節點是葉子節點,權值為x。

一行,最少逆序對個數。 3

0031

21對於100%的資料:2<=n<=200000。

題解:可以發現每次交換對子樹內的逆序對數沒有影響。

所以我們可以使每棵子樹都最優。

我們對每個葉子節點維護一棵權值線段樹,自底向上更新.

更新的時候列舉是否需要交換,然後把兩棵線段樹合併即可.

注意動態開點.

**:#include#include#include#define n 400010

using namespace std;

int cnt,t[n*10],root[n],ls[n*10],rs[n*10],v[n],n,l[n],r[n],sz;

long long ans,a,b;

void buildtree(int x)

}void update(int k)

void build(int &k,int l,int r,int v)

int mid=(l+r)>>1;

if (v<=mid) build(ls[k],l,mid,v);

else build(rs[k],mid+1,r,v);

update(k);

}int merge(int x,int y)

void solve(int x)

}int main(){

scanf("%d",&n);

sz=1;buildtree(1);

for (int i=1;i<=sz;i++)

if (v[i]) build(root[i],1,n,v[i]);

solve(1);

cout<

bzoj 3702 二叉樹 (線段樹)

time limit 15 sec memory limit 256 mb submit 428 solved 184 submit status discuss 現在有一棵二叉樹,所有非葉子節點都有兩個孩子。在每個葉子節點上有乙個權值 有n個葉子節點,滿足這些權值為1.n的乙個排列 可以任意交換每...

bzoj3702 二叉樹 權值線段樹

神奇的解法 對於每個節點,建出權值線段樹 每次查詢右子樹的權值線段樹和左子樹的權值線段樹,左子樹中比右子樹小的有多少?右子樹比左子樹小的有多少?分別對應不交換的逆序對和交換的逆序對 將左子樹和右子樹的權值線段樹合併 遞迴進行這個操作 感覺複雜度很不靠譜,於是想證明一下複雜度 最開始權值線段樹共o n...

BZOJ2212 二叉樹 線段樹合併

這道題給人的第一感覺像是樹形 include define maxn 400010 define reg register define cmin x,y x y using namespace std int n,tot,w maxn lson maxn rson maxn root maxn 原...