bzoj3702 二叉树

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3702

【题解】

卧槽这竟然是bzoj的题(没想到)

啊很明显我们对于每个节点 判断一下两边交换/不交换哪个逆序对贡献的少就行了

至于这个逆序对贡献啊?线段树合并!

啊我不会线段树合并啊?启发式合并(dsu on tree)

# include <vector>
# include <stdio.h>
# include <assert.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 5e5 + 10;
const int mod = 1e9+7;

# define RG register
# define ST static

int n, siz, rt, ch[M][2], siz2;
int val[M], a[M], m, sz[M], sz2[M];
vector<int> ps;

struct BIT {
    int c[M], n;
    # define lb(x) (x&(-x))
    inline void set(int _n) {
        n = _n;
        memset(c, 0, sizeof c);
    }
    inline void edt(int x, int d) {
        for (; x<=n; x+=lb(x)) c[x] += d;
    }
    inline int sum(int x) {
        int ret=0;
        for (; x; x-=lb(x)) ret += c[x];
        return ret;
    }
    inline int sum(int l, int r) {
        if(l>r) return 0;
        return sum(r)-sum(l-1);
    }
}T;

inline void dfs(int &x) {
    int t; scanf("%d", &t);
    if(t == 0) x = ++siz;
    else x = ++siz2;
    sz[x] = 1;
    if(t == 0) {
        dfs(ch[x][0]);
        dfs(ch[x][1]);
        sz[x] += sz[ch[x][0]] + sz[ch[x][1]];
        sz2[x] = sz2[ch[x][0]] + sz2[ch[x][1]];
    } else {
        sz2[x] = 1;
        val[x] = t;
        ps.push_back(t);
    }    
}

bool big[M];
ll cura = 0, curb;
inline void calc(int x) {
    if(val[x] != 0) {
        cura += T.sum(val[x]+1, n);
        curb += T.sum(val[x]-1);
        return ;
    }
    if(!big[ch[x][0]]) calc(ch[x][0]);
    if(!big[ch[x][1]]) calc(ch[x][1]);
}

inline void del(int x, int d) {
    if(x <= n) {
        T.edt(val[x], d);
        return ;
    }
    if(!big[ch[x][0]]) del(ch[x][0], d);
    if(!big[ch[x][1]]) del(ch[x][1], d);
}

ll ans = 0;
inline void dsu(int x, bool kep) {
    if(x <= n) {
        if(kep) T.edt(val[x], 1);
        return;
    }
    int bc, sc;
    if(sz[ch[x][0]] > sz[ch[x][1]]) bc = ch[x][0], sc = ch[x][1];
    else bc = ch[x][1], sc = ch[x][0];
    dsu(sc, 0);
    dsu(bc, 1);
//    printf("x=%d, query=%d\n", x, T.sum(1, n));
    big[bc] = 1;
    cura = curb = 0;
    calc(x); del(x,1);
    ans += min(cura, curb);
    big[bc] = 0; 
    if(kep == 0) del(x,-1);        
}

int main() {
    cin >> n; 
    siz = n; dfs(rt);
    T.set(n);
    sort(ps.begin(), ps.end());
    ps.erase(unique(ps.begin(), ps.end()), ps.end());
    for (int i=1; i<=siz; ++i)
        if(val[i] != 0) val[i] = lower_bound(ps.begin(), ps.end(), val[i]) - ps.begin() + 1;
//    for (int i=1; i<=siz; ++i) printf("x=%d, ls=%d, rs=%d\n", i, ch[i][0], ch[i][1]);
    dsu(rt, 1);
    cout << ans << endl;
    return 0;
}
View Code

 

posted @ 2017-05-31 15:29  Galaxies  阅读(288)  评论(0编辑  收藏  举报