bzoj 2212 [Poi2011]Tree Rotations(线段树合并)

96 篇文章 0 订阅
64 篇文章 0 订阅

题意:

一棵二叉树有n个叶子节点,每个叶子节点有权值,可以交换左右子树,问先序遍历这棵树,得到的最小逆序对数。


思路:

应该算是线段树合并的入门题。


暴力每个非叶子节点,用ans1记录不交换左右子树时,跨越左子树和右子树的答案,即左子树大于右子树的数的对数,ans2记录交换左右子树时的答案。


查询左子树中大于右子树的对数可以对左右子树各建一棵权值线段树,在线段树合并的过程中,左子树的线段树的右区间的值一定大于右子树的左区间的值,统计一下,就好了。


代码:

#include <bits/stdc++.h>
#define MID int mid=(l+r)>>1;
#define LL long long 
using namespace std;
const int maxn=4e5+5;
int root[maxn], n, top, siz[maxn*2+1], a[maxn*2+1],  ll[maxn*2+1], rr[maxn*2+1];
LL ans[maxn*2+1], ans1, ans2;
int lson[maxn*10], rson[maxn*10];
LL val[maxn*10];
int cnt;
int tot;
void read(int &x)
{
    scanf("%d", &a[tot]);   
    x=tot;
    siz[x]=1;
    tot++;
    if(a[x]==0)
    {
        read(ll[x]);read(rr[x]);
        siz[x]+=siz[ll[x]]+siz[rr[x]];
    }
    return;
}
void insert(int &root, int l, int r, int x)
{
    if(root==0)root=++cnt;
    val[root]=1;
    if(l==r)
    {
        return;
    }
    MID
    lson[root]=rson[root]=0;
    if(x<=mid)insert(lson[root], l, mid, x);
    else insert(rson[root], mid+1, r, x); 
}
 
int merg( int rtl, int rtr)
{
    if(rtl==0 || rtr==0)return rtl|rtr;
    ans1+=(val[rson[rtl]]*val[lson[rtr]]);
    ans2+=(val[lson[rtl]]*val[rson[rtr]]);
    val[rtl]+=val[rtr];
    lson[rtl]=merg(lson[rtl], lson[rtr]);
    rson[rtl]=merg(rson[rtl], rson[rtr]);
    return rtl;
}
LL ANS;
void dfs(int x)
{
    if(a[x])return;
    if(siz[ll[x]]>siz[rr[x]]){dfs(ll[x]);dfs(rr[x]);}
    else {dfs(rr[x]); dfs(ll[x]);}
//    printf("%d %d\n", ll[x], rr[x]);
    ans1=0, ans2=0;
    root[x]=merg(root[ll[x]], root[rr[x]]);
    ANS+=ans1<ans2?ans1:ans2;
    return;
}
 
int main()
{
    int i, j;
    cin>>n;
    tot=0;
    read(top);   
    for(i=0; i<tot; i++)
    {
        if(a[i]!=0)insert(root[i], 1, n, a[i]);
    }
    dfs(top);
    printf("%lld\n", ANS);
     
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值