zoukankan      html  css  js  c++  java
  • BZOJ 2212: [Poi2011]Tree Rotations(线段树合并)

    传送门

    解题思路

      线段树合并,考虑交换两个子树时,对除这两棵子树外的其余点的逆序对不会造成影响,所以我们只需要贪心的使这两棵子树产生的逆序对最小。而考虑时我们也只需要考虑两棵子树间的逆序对数,不需要考虑每棵子树内部逆序对数,这样就非常好算了,可以线段树合并,合并的同时统计一下交换前和后的逆序对数,然后取个(min)加到答案里。

    代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    
    using namespace std;
    const int N=200005;
    typedef long long LL;
    
    inline int rd(){
        int x=0,f=1; char ch=getchar();
        while(!isdigit(ch)) f=ch=='-'?9:1,ch=getchar();
        while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
        return f?x:-x;	
    }
    
    int n,tot,sum[N<<5],ls[N<<5],rs[N<<5];
    LL ans,res1,res2;
    
    int update(int l,int r,int pos){
        int now=++tot; sum[now]=1; 
        if(l==r) return now; int mid=(l+r)>>1;
        if(pos<=mid) ls[now]=update(l,mid,pos);
        else rs[now]=update(mid+1,r,pos);
        sum[now]=sum[ls[now]]+sum[rs[now]];
        return now;
    }
    
    int merge(int u,int v,int l,int r){
        if(!u || !v) return (u|v);
        if(l==r) {sum[++tot]=sum[u]+sum[v]; return tot;}
        int mid=(l+r)>>1;	
        res1+=(LL)sum[rs[u]]*sum[ls[v]],res2+=(LL)sum[ls[u]]*sum[rs[v]];
        ls[u]=merge(ls[u],ls[v],l,mid); rs[u]=merge(rs[u],rs[v],mid+1,r);
        sum[u]+=sum[v]; return u;
    }
    
    int DFS(){
        int now=rd(),tmp,LS,RS;
        if(now) return update(1,n,now);
        LS=DFS(); RS=DFS(); tmp=merge(LS,RS,1,n);
        ans+=min(res1,res2); res1=res2=0;
        return tmp;
    }
    
    int main(){
        n=rd(); DFS();
        printf("%lld",ans);
        return 0;	
    }
    
  • 相关阅读:
    MYbatis调试日记(三)
    Mybatis错误调试(二)
    【转载】MyBatis之传入参数
    Mybatis代码调试问题总结(一)
    【转载】Mybatis多参数查询映射
    未整理的资源
    Strace--系统调用分析问题集锦
    java初始化过程中成员变量
    java三元表达式编程规范问题
    转:Java的一道面试题----静态变量初始化过程
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/10350472.html
Copyright © 2011-2022 走看看