zoukankan      html  css  js  c++  java
  • 【Luogu】P3521ROT-Tree Rotations(线段树合并)

      题目链接

      神奇的线段树合并qwq   不过就思路而言很好想……

      观察到一棵树无论怎么交换两棵左右子树,子树内部的最优逆序对并没影响……决策只影响左右子树之间的逆序对……

      于是线段树合并直接乱搞就好啦

      

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cctype>
    #define mid ((l+r)>>1)
    #define check(x) if(x==0)    x=++tot;
    #define maxn 400200
    using namespace std;
    inline long long read(){
        long long num=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-')    f=-1;
            ch=getchar();
        }
        while(isdigit(ch)){
            num=num*10+ch-'0';
            ch=getchar();
        }
        return num*f;
    }
    
    long long ls[maxn];
    long long rs[maxn];
    long long q[maxn];
    long long root[maxn];
    long long lc[maxn*10];
    long long rc[maxn*10];
    long long tree[maxn*10];
    long long f[maxn];
    long long c,w;
    long long ans;
    long long n,tot,cnt;
    
    inline void pushup(long long rt){    tree[rt]=tree[lc[rt]]+tree[rc[rt]];    }
    
    void update(long long o,long long l,long long r,long long &rt){
        check(rt);
        if(l==r){
            tree[rt]++;    return;
        }
        if(o<=mid)    update(o,l,mid,lc[rt]);
        else        update(o,mid+1,r,rc[rt]);
        pushup(rt);
    }
    
    void gettree(long long &x){
        x=++cnt;
        q[x]=read();
        if(q[x])    return;
        gettree(ls[x]);
        gettree(rs[x]);
        return;
    }
    
    long long merge(long long x,long long y){
        if(x==0)    return y;
        if(y==0)    return x;
        c+=tree[rc[x]]*tree[lc[y]];
        w+=tree[lc[x]]*tree[rc[y]];
        lc[x]=merge(lc[x],lc[y]);
        rc[x]=merge(rc[x],rc[y]);
        pushup(x);
        return x;
    }
    
    void calc(long long x){
        if(q[x])    return;
        calc(ls[x]);
        calc(rs[x]);
        c=w=0;
        root[x]=merge(root[ls[x]],root[rs[x]]);
        ans+=min(c,w);
        return;
    }
    
    void build(long long x){
        if(q[x]){
            update(q[x],1,n,root[x]);
            return;
        }
        build(ls[x]);
        build(rs[x]);
        return;
    }
    
    long long Root;
    
    int main(){
        n=read();
        gettree(Root);
        build(1);
        calc(1);
        printf("%lld",ans);
        return 0;
    }
  • 相关阅读:
    二叉树前、中、后遍历
    程序员节宜冒泡
    HashMap源码分析
    Stack源码解析
    逆袭之旅DAY24.XIA.二重进阶、双色球
    逆袭之旅DAY24.XIA.数组练习
    LY.JAVA面向对象编程.内部类
    LY.JAVA面向对象编程.修饰符
    LY.JAVA面向对象编程.包的概述、导包
    XIA.人机猜拳
  • 原文地址:https://www.cnblogs.com/cellular-automaton/p/8364693.html
Copyright © 2011-2022 走看看