zoukankan      html  css  js  c++  java
  • [POI2011]ROT-Tree Rotations

    发现x的子树在后续处理中不会影响逆序对的情况(只关心有哪些值,相对位置已经不重要了)

    f[x]表示x为根的子树最小逆序对数

    考虑左右儿子交换与否。

    暴力是O(n^2)的

    考虑线段树合并

    左右儿子线段树合并的时候,直接类似于分治,记录另一棵数小于某个数的个数,

    选择代价小的放在前面

    具体看代码:

    1.x,y别写错。。。

    2.开long long,而且线段树可能存在一个点的sz大于n,乘起来会爆int

    #include<bits/stdc++.h>
    #define reg register int
    #define mid ((l+r)>>1)
    #define il inline
    #define numb (ch^'0')
    using namespace std;
    typedef long long ll;
    il void rd(int &x){
        char ch;x=0;bool fl=false;
        while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
        for(x=numb;isdigit(ch=getchar());x=x*10+numb);
        (fl==true)&&(x=-x);
    }
    namespace Miracle{
    const int N=200000+5;
    int n,ch[2*N][2];
    struct tr{
        int ls,rs;
        int sz;
    }t[40*N];
    int tot;
    void pushup(int x){
        t[x].sz=t[t[x].ls].sz+t[t[x].rs].sz;
    }
    ll xfsz,yfsz;
    int rt[2*N],m;
    ll f[2*N];
    int merge(int x,int y,int l,int r){
        if(!x||!y) return x+y;
        if(l==r){
            t[x].sz+=t[y].sz;
            return x;    
        }
        xfsz+=(ll)t[t[x].rs].sz*t[t[y].ls].sz;
        yfsz+=(ll)t[t[y].rs].sz*t[t[x].ls].sz;
        t[x].ls=merge(t[x].ls,t[y].ls,l,mid);
        t[x].rs=merge(t[x].rs,t[y].rs,mid+1,r);
        pushup(x);
        return x;
    }
    void upda(int &x,int l,int r,int p){
        if(!x) x=++tot;
        if(l==r){
            t[x].sz=1;
            return;
        }
        if(p<=mid) upda(t[x].ls,l,mid,p);
        else upda(t[x].rs,mid+1,r,p);
        pushup(x);
    }
    void build(int &x){
        x=++m;
        int val;rd(val);
        if(val==0){
            build(ch[x][0]);build(ch[x][1]);
        }else{
            upda(rt[x],1,n,val);
        }
    }
    void dfs(int x){
        if(ch[x][0]&&ch[x][1]){
            dfs(ch[x][0]),dfs(ch[x][1]);
        //    cout<<" back to "<<x<<endl;
            xfsz=0;yfsz=0;
            rt[x]=rt[ch[x][0]];
            rt[x]=merge(rt[x],rt[ch[x][1]],1,n);
            f[x]=f[ch[x][0]]+f[ch[x][1]]+min(xfsz,yfsz);
        //    cout<<" xfsz "<<xfsz<<" yfsz "<<yfsz<<endl;
        //    cout<<" f[x] "<<f[x]<<endl;
        }
    }
    int main(){
        rd(n);
        int haha;
        build(haha);
        dfs(1);
        printf("%lld
    ",f[1]);
        return 0;
    }
    
    }
    signed main(){
    //    freopen("4.in","r",stdin);
    //    freopen("4.out","w",stdout);
        Miracle::main();
        return 0;
    }
    
    /*
       Author: *Miracle*
       Date: 2019/2/10 11:57:09
    */
  • 相关阅读:
    大数据学习之路(持续更新中...)
    数据挖掘之初级
    用户画像
    机器挖掘之经典算法
    算法时间复杂度
    01-IOS-越狱指南
    gradle 内容学习参考
    python 获取文件路径相关
    第一行代码阅读笔记
    使用同步锁防止多进程的并发操作
  • 原文地址:https://www.cnblogs.com/Miracevin/p/10359309.html
Copyright © 2011-2022 走看看