80: bzoj3705 线段树合并

$des$

现在有一棵二叉树,所有非叶子节点都有两个孩子。在每个叶子节点上有一个权值(有n个叶子节点,满足这些权值为1..n的一个排列)。可以任意交换每个非叶子节点的左右孩子。
要求进行一系列交换,使得最终所有叶子节点的权值按照中序遍历写出来,逆序对个数最少。

$sol$

可以发现每次交换对子树内的逆序对数没有影响。所以我们可以使每棵子树都最优。

对每个叶子节点维护一棵权值线段树,自底向上更新.

 更新的时候枚举是否需要交换,然后把两棵线段树合并即可.

注意动态开点.

#include<bits/stdc++.h>

#define ll long long

using namespace std;

#define Rep(i, a, b) for(int i = a; i <= b; i ++)


#define gc getchar()
inline int read() {
    int x = 0, f = 1;
    char c = gc;
    while(c < '0' || c > '9') {
        if(c == '-') f = -1;
        c = gc;
    }
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc;
    return x * f;
}

int n, sz, seg;
ll ans, cnt1, cnt2;
int v[400005], l[400005], r[400005], root[400005];
int sum[4000005], ls[4000005], rs[4000005];

namespace $ {
    void readtree(int x) {
        v[x] = read();
        if(!v[x]) {
            l[x] = ++ sz;
            readtree(l[x]);
            r[x] = ++ sz;
            readtree(r[x]);
        }
    }

    void pushup(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] = 1;
            return;
        }
        int mid = (l + r) >> 1;
        if(val <= mid) build(ls[k], l, mid, val);
        else build(rs[k], mid + 1, r, val);
        pushup(k);
    }

    int merge(int x,int y) {
        if(!x) return y;
        if(!y) return x;
        cnt1 += (ll)sum[rs[x]] * sum[ls[y]];
        cnt2 += (ll)sum[ls[x]] * sum[rs[y]];
        ls[x] = merge(ls[x], ls[y]);
        rs[x] = merge(rs[x], rs[y]);
        pushup(x);
        return x;
    }

    void solve(int x) {
        if(!x) return;
        solve(l[x]);
        solve(r[x]);
        if(!v[x]) {
            cnt1 = cnt2 = 0;
            root[x] = merge(root[l[x]], root[r[x]]);
            ans += min(cnt1,cnt2);
        }
    }
}

int main() {
    n = read();
    ++ sz;
    $:: readtree(1);
    Rep(i, 1, sz)
    if(v[i]) $:: build(root[i], 1, n, v[i]);
    $:: solve(1);
    cout << ans;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/shandongs1/p/9863565.html