【BZOJ2212】[POI2011]Tree Rotations (线段树合并)

题解:

傻逼题

启发式合并线段树里面查$nlog^2$

线段树合并顺便维护一下$nlogn$

注意是叶子为n 总结点2n

代码:

#include <bits/stdc++.h>
using namespace std;
#define rint register int
#define IL inline
#define rep(i,h,t) for(int i=h;i<=t;i++)
#define dep(i,t,h) for(int i=t;i>=h;i--)
#define ll long long
#define me(x) memset(x,0,sizeof(x))
#define mep(x,y) memcpy(x,y,sizeof(y))
#define mid (t<=0?(h+t-1)/2:(h+t)/2)
namespace IO{
    char ss[1<<24],*A=ss,*B=ss;
    IL char gc()
    {
        return A==B&&(B=(A=ss)+fread(ss,1,1<<24,stdin),A==B)?EOF:*A++;
    }
    template<class T> void read(T &x)
    {
        rint f=1,c; while (c=gc(),c<48||c>57) if (c=='-') f=-1; x=(c^48);
        while (c=gc(),c>47&&c<58) x=(x<<3)+(x<<1)+(c^48); x*=f; 
    }
    char sr[1<<24],z[20]; int Z,C1=-1;
    template<class T>void wer(T x)
    {
        if (x<0) sr[++C1]='-',x=-x;
        while (z[++Z]=x%10+48,x/=10);
        while (sr[++C1]=z[Z],--Z);
    }
    IL void wer1()
    {
        sr[++C1]=' ';
    }
    IL void wer2()
    {
        sr[++C1]='\n';
    }
    template<class T>IL void maxa(T &x,T y) {if (x<y) x=y;}
    template<class T>IL void mina(T &x,T y) {if (x>y) x=y;} 
    template<class T>IL T MAX(T x,T y){return x>y?x:y;}
    template<class T>IL T MIN(T x,T y){return x<y?x:y;}
};
using namespace IO;
const int N1=4.1e5;
const int N2=7e6;
int ch[N1][2],node,v[N1],rt[N1],n;
ll ans,cnt1,cnt2;
int gettree()
{
    int x,u=++node;read(x);
    if(!x)ch[u][0]=gettree(),ch[u][1]=gettree();
    else v[u]=x;
    return u;
}
struct sgt{
    int sum[N2],ls[N2],rs[N2],cnt;
    void insert(int &x,int h,int t,int pos)
    {
        x=++cnt; sum[x]=1;
        if (h==t) return;
        if (pos<=mid) insert(ls[x],h,mid,pos);
        else insert(rs[x],mid+1,t,pos);
    }
    int merge(int x,int y)
    {
        if (!x||!y) return x^y;
        sum[x]+=sum[y]; 
        cnt1+=1ll*sum[ls[x]]*sum[rs[y]];
        cnt2+=1ll*sum[rs[x]]*sum[ls[y]];
        ls[x]=merge(ls[x],ls[y]);
        rs[x]=merge(rs[x],rs[y]);
        return x;
    }
}S;
void dfs(int x)
{
    if (v[x])
    {
        S.insert(rt[x],1,n,v[x]); return;
    } 
    dfs(ch[x][0]);
    dfs(ch[x][1]);
    cnt1=0,cnt2=0;
    rt[x]=S.merge(rt[ch[x][0]],rt[ch[x][1]]);
    ans+=MIN(cnt1,cnt2);
}
int main()
{
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    read(n); gettree();
    dfs(1);
    cout<<ans<<endl;
    return 0;
}

 

posted @ 2018-12-04 14:17  尹吴潇  阅读(121)  评论(0编辑  收藏  举报