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; 
} 
posted @ 2018-07-24 19:58  zzzzx  阅读(93)  评论(0编辑  收藏  举报