[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
*/
原文地址:https://www.cnblogs.com/Miracevin/p/10359309.html