• bzoj 2212: [Poi2011]Tree Rotations


    题目链接

    bzoj 2212: [Poi2011]Tree Rotations

    题解

    一个子树之内交换儿子,对子树之外没有影响
    所以对于每个节点的子数,交换与不交换,左右子树间形成的逆序对取min
    每个节点维护权值线段树,线段树合并

    代码

     
    #include<bits/stdc++.h> 
    using namespace std;
    inline int read() {
        int x = 0,f = 1;char c = getchar(); 
        while(c < '0' || c > '9'){if(c == '-') f= - 1; c = getchar();}  
        while(c <= '9' &&c >= '0')x = x * 10 + c- '0',c = getchar(); 
        return x * f; 
    } 
    const int maxn = 2000007; 
    int n,tmp,sz[maxn * 10],lc[maxn * 10],tot = 0,rc[maxn * 10]; 
    long long ans = 0,res1 = 0,res2 = 0; 
    int insert(int l,int r,int rk) { 
        sz[++ tot] = 1; 
        if(l == r) return tot; 
        int mid = l + r >> 1,rt = tot; 
        if(rk <= mid) lc[rt] = insert(l,mid,rk); 
        else rc[rt] = insert(mid + 1,r,rk); 
        return rt;  
    } 
    int  merge(int l,int r,int x,int y) { 
        if(! x || ! y) return x ^ y; 
        if(l == r) { sz[ ++ tot] = sz[x] + sz[y];  return tot; } 
        int mid = l + r >> 1,rt = ++ tot; 
        res1 += 1ll * sz[rc[x]] * sz[lc[y]] , res2 += 1ll * sz[lc[x]] * sz[rc[y]];  
        lc[rt] = merge(l,mid,lc[x],lc[y]); 
        rc[rt] = merge(mid + 1,r,rc[x],rc[y]); 
        sz[rt] = sz[lc[rt]] + sz[rc[rt]]; 
        return rt; 
    } 
    int dfs() { 
        tmp = read(); 
        if(tmp) return insert(1,n,tmp); 
        int rt = merge(1,n,dfs(),dfs()); 
        ans += min(res1,res2); 
        res1 = res2 = 0; 
        return rt; 
    }  
    int main() { 
        n = read(); 
        dfs(); 
        cout << ans << endl; 
        return 0; 
    } 
    
  • 相关阅读:
    目录路径加反斜杠和不加的区别
    window端口号被占用解决
    个人博客设计记录
    2017/12/15
    添加code到github上
    跨域简介
    客户端存储
    window.name跨域
    BZOJ1305: [CQOI2009]dance跳舞
    BZOJ4872: [Shoi2017]分手是祝愿
  • 原文地址:https://www.cnblogs.com/sssy/p/9362236.html
Copyright © 2020-2023  润新知