zoukankan      html  css  js  c++  java
  • 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
    ", 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
    ", i, ch[i][0], ch[i][1]);
        dsu(rt, 1);
        cout << ans << endl;
        return 0;
    }
    View Code
  • 相关阅读:
    如何实现parseFloat保留小数点后2位
    C#正则表达式整理备忘
    HRESULT:0x80070057 (E_INVALIDARG)的异常的解决方案
    c# using的几种用法
    QQ截图 有快捷键的,如Shift+S
    史上最深刻的黄段子
    文本框回车自动提交
    C#与ASP.NET中DateTime.Now函数详解
    ASP.NET页面生命周期
    .NET中HttpWebRequest详解
  • 原文地址:https://www.cnblogs.com/galaxies/p/bzoj3702.html
Copyright © 2011-2022 走看看